Search NSArray for value matching value

独自空忆成欢 提交于 2019-11-27 04:30:33

With your current data structures, you can only do it in O(n^2) time by looping over the first array once for each member of the second array:

NSMutableArray * array = [NSMutableArray array];
for (NSString * name in names) {
    for (MyObject * object in objects) {
        if ([[myObject name] isEqualToString:name]) {
            [array addObject:object];
        }
    }
}

(Alternate as suggested by Stefan: loop over the objects array and ask the names array if it containsObject: for the name of each object.)

But if this really needs to be faster (really depends on the size of the arrays as much as how often you do it), you can improve this by introducing an NSDictionary that maps the names in the first array to their objects. Then each of those lookups is O(1) and the overall time is O(n). (You'd have to keep this dictionary always in sync with the array of objects, which isn't hard with reasonable accessors. This technique also has the constraint that the same name can't appear on more than one object.)

An alternate way of getting this result (and which doesn't have that last constraint) is to use an NSSet for your second collection, then walk through the objects array calling containsObject: with each one on the set of names. Whether this technique is better depends on whether your two collections are roughly the same size, or if one is much larger than the other.

Why not just to use predicates to do that for you?:

// For number kind of values:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF = %@", value];
NSArray *results = [array_to_search filteredArrayUsingPredicate:predicate];

// For string kind of values:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", value];
NSArray *results = [array_to_search filteredArrayUsingPredicate:predicate];

// For any object kind of value (yes, you can search objects also):
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", value];
NSArray *results = [array_to_search filteredArrayUsingPredicate:predicate];
Stephen Poletto

Here's a simple way:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", nameToFind];
[listOfItems filteredArrayUsingPredicate:predicate];

I like to use this method:

NSIndexSet *indexes = [_items indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
   return ((MyObject *)obj).name isEqualToString:name];
}];

if (indexes.count != 0) {
//extract your objects from the indexSet, and do what you like...
}
NSMutableArray * foundNames = [NSMutableArray array];
for (MyObject * objectWithName in objectCollection) {
    if ([names containsObject:objectWithName.name]) {
        [foundNames objectWithName];
    }
}
NWCoder

The methods most helpful will be:

filteredArrayUsingPredicate:

and

indexesOfObjectsPassingTest:

The second one uses a code block, not available on iOS before 4.0

Both of these will be more efficient than iterating directly.

There's a good example here: http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxUsing.html

NSMutableArray* solutions = [NSMutableArray array];

for (Object* object in objects){
   for (NSString* name in names){
       if ([object.name isEqualToString:name]){
          [solutions addObject:object];
          break; // If this doesnt work remove this
       }
   }
}
kabeer
int count=0;

if (range.location!=NSNotFound)
  {                   
  [searchindex addObject:[NSString stringWithFormat:@"%d",count]];           
  }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!