在NSArray中搜索值匹配值

时间:2011-03-07 21:01:18

标签: iphone objective-c ipad nsarray

我有一个objects的NSArray,它有一个名为name的特殊属性(类型为NSString)。
我有第二个NSStrings的NSArray是names

我想获得objects所有.name属性与第二个NSArray中的names之一相匹配的NSArray。

我如何快速有效地解决这个问题,因为这将经常需要。

8 个答案:

答案 0 :(得分:72)

为什么不只是使用谓词为你做这件事?:

// 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];

答案 1 :(得分:14)

使用您当前的数据结构,您只能在O(n ^ 2)时间内通过为第二个数组的每个成员循环第一个数组执行一次:

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

(Stefan建议的替代方法:循环遍历对象数组,并询问名称数组是否containsObject:作为每个对象的名称。)

但是如果这真的需要更快(实际上取决于数组的大小和你执行频率的程度),你可以通过引入一个映射第一个数组中names的NSDictionary来改善这一点。对他们的对象。然后,每个查找都是O(1),总时间是O(n)。 (你必须保持这个字典始终与对象数组同步,这对于合理的访问器来说并不难。这种技术还有一个约束,即同一个name不能出现在多个对象上。)

获得此结果的另一种方法(并且没有最后一个约束)是为第二个集合使用NSSet,然后遍历调用containsObject:的对象数组,每个集合都在名。这种技术是否更好取决于你的两个系列是否大致相同,或者一个是否比另一个大得多。

答案 2 :(得分:14)

这是一个简单的方法:

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

答案 3 :(得分:6)

我喜欢使用这种方法:

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...
}

答案 4 :(得分:2)

NSMutableArray * foundNames = [NSMutableArray array];
for (MyObject * objectWithName in objectCollection) {
    if ([names containsObject:objectWithName.name]) {
        [foundNames objectWithName];
    }
}

答案 5 :(得分:2)

最有用的方法是:

filteredArrayUsingPredicate:

indexesOfObjectsPassingTest:

第二个使用代码块,在4.0之前的iOS上不可用

这两种方法都比直接迭代更有效。

这里有一个很好的例子: http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxUsing.html

答案 6 :(得分:0)

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
       }
   }
}

答案 7 :(得分:0)

int count=0;

if (range.location!=NSNotFound)
  {                   
  [searchindex addObject:[NSString stringWithFormat:@"%d",count]];           
  }