How to search an NSSet or NSArray for an object which has an specific value for an specific property?
How to search an NSSet or NSArray for an object which has an specific value for an specific property?
Example: I have an NSSet with 20 objects, and every object has an type
property. I want to get the first object which has [theObject.type isEqualToString:@"standard"]
.
I remember that it was possible to use predicates somehow for this kind of stuff, right?
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type == %@", @"standard"];
NSArray *filteredArray = [myArray filteredArrayUsingPredicate:predicate];
id firstFoundObject = nil;
firstFoundObject = filteredArray.count > 0 ? filteredArray.firstObject : nil;
NB: The notion of the first found object in an NSSet makes no sense since the order of the objects in a set is undefined.
You can get the filtered array as Jason and Ole have described, but since you just want one object, I'd use - indexOfObjectPassingTest:
(if it's in an array) or -objectPassingTest:
(if it's in a set) and avoid creating the second array.
Generally, I use indexOfObjectPassingTest:
as I find it more convenient to express my test in Objective-C code rather than NSPredicate
syntax. Here's a simple example (imagine that integerValue
was actually a property):
NSArray *array = @[@0,@1,@2,@3];
NSUInteger indexOfTwo = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return ([(NSNumber *)obj integerValue] == 2);
}];
NSUInteger indexOfFour = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return ([(NSNumber *)obj integerValue] == 4);
}];
BOOL hasTwo = (indexOfTwo != NSNotFound);
BOOL hasFour = (indexOfFour != NSNotFound);
NSLog(@"hasTwo: %@ (index was %d)", hasTwo ? @"YES" : @"NO", indexOfTwo);
NSLog(@"hasFour: %@ (index was %d)", hasFour ? @"YES" : @"NO", indexOfFour);
The output of this code is:
hasTwo: YES (index was 2)
hasFour: NO (index was 2147483647)
NSArray* results = [theFullArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.type LIKE[cd] %@", @"standard"]];