How to search an NSSet or NSArray for an object which has an specific value for an specific property?
Asked Answered
G

4

53

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?

Gocart answered 19/6, 2010 at 17:16 Comment(0)
M
81
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.

Milda answered 19/6, 2010 at 17:23 Comment(3)
Does it work if the object doesn't have the 'type' property, but has another object (let's say 'job'), and this is 'job' which has the 'type' property?Zinc
Yes, but a class must be key-value coding compliant for the keys you want to use in a predicate.Therapsid
indexOfObjectPassingTest seems better for two reasons: (1) You use an actual method rather than a string (2) You stop on the "first" element you find - it doesn't matter that a set is not ordered, you may still want just one item.Sandisandidge
H
17

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.

Hundred answered 20/6, 2010 at 21:19 Comment(1)
That seems a good idea for an NSArray, but the method in NSSet is actually -objectsPassingTest: (note the plural), so this idea isn't directly possible there, if I understand this correctly.Pubis
H
15

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)
Handball answered 16/8, 2013 at 14:25 Comment(0)
F
5
NSArray* results = [theFullArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.type LIKE[cd] %@", @"standard"]];
Formative answered 19/6, 2010 at 17:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.