Search code examples
iosxcodensarraynspredicate

How to filter array based on dictionary key?


I have an array of objects. The objects in the array contain a dictionary as one of its properties and i need to search the values of one of those keys for each object within the array. I need to use a like condition(I think its actually contains in objective-c I may be wrong though). Im using the method _search_results = [_people filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"details[@\"firstName\"] contains %@",searchBar.text]]; which i think will return me all the objects that fit that search condition. Here are my questions

1) Is there another method I can use to do this? Or maybe a different class all in general? Maybe a more efficient method to use? 2) Am i going about searching for the value correctly within the dictionary? Since its a property of the object i think im doing it right. Which the syntax to me looks correct dictionaryName[keyName] contains value

Ive only use NSPredicate with properties of objects, i never had to search a dictionary thats in an object like this. So like i said I think im right here.

In response to the first set of answers

_search_results = [_people indexesOfObjectsPassingTest:^BOOL(PeopleObject *person, NSUInteger idx, BOOL * _Nonnull stop) {

    NSString *last_name = person.details[kPersonLastNameKey];
    if([last_name containsString:searchBar.text]){
        return TRUE;
    }
    else 
        return FALSE;
}];

Solution

  • There are at least a half-dozen ways to do this. You don't say if you're using Objective-C or Swift, although the sample code you show looks like Objective-C.

    If you were using Swift you could use the built-in Swift filter function, but let's forgo that.

    You could use filteredArrayUsingPredicate, as you're doing now.

    You could use indexesOfObjectsPassingTest to build an NSIndexSet of the objects in your array that meet your criteria (That method takes a block, and for all objects where your block returns true, the resulting index set includes the index of the object. You'd then use objectsAtIndexes to return an array of the objects listed in the index set.

    I haven't benchmarked it, but I suspect that for large arrays, the predicate method is slower, since predicates are a very flexible method of selecting objects, and flexible code tends to be slower code. However, unless you are filtering tens of thousands of objects, or more, I doubt if you'd even notice the difference in performance.

    Don't fall into the trap of premature optimization - wasting your time and making your code more complex to optimize things that do not have a meaningful impact on your app's performance.

    Unless your app is running noticeably slowly, and you've tested it and determined that the array filtering has a significant influence on that slowness, it's probably not worth worrying about.