NSArray找到对象或对象 - 最佳实践

Upt*_*pps 28 objective-c nsarray ios

解决方案: 我已将@ BlackRider的答案标记为正确,因为它是最通用的,特别是对于复杂的比较,但还有其他非常好的答案和评论.我会鼓励任何有相同或类似问题的人对其进行审核,并针对您的具体情况评估最佳行动方案.

在我的情况下,我实际上并没有在我的实现中使用BlackRider的解决方案.在@ JoshCaswell的评论以及@ voromax的建议下indexesOfObjectsWithOptions:passingTest:,我选择使用我自己的解决方案(参见下面的编辑#2),因为在这种情况下我的比较非常简单.

感谢所有回答并提供见解的人.


我正在寻找一种有效的方法来从NSArray基于该对象的属性(在这种情况下是唯一标识符)中检索对象.在使用Linq的C#.NET中,我会做类似的事情

MyObject obj = myList.Single(o => o.uuid == myUUID);
Run Code Online (Sandbox Code Playgroud)

我也想知道是否有一种有效的方法来获得匹配非唯一属性的对象数组.再次,与Linq一样,它看起来像

List<MyObject> objs = myList.Where(o => o.flag == true).ToList();
Run Code Online (Sandbox Code Playgroud)

当然,我可以编写循环来执行此操作,但它们不可重用,我对它们的性能持怀疑态度.

查找具有唯一ID的对象:

-(MyObject*)findObjectWithUUID:(NSString*)searchUUID{
    for (MyObject* obj in _myArray){
        if([obj.uuid isEqualToString: searchUUID])
            return obj;
    }
}
Run Code Online (Sandbox Code Playgroud)

查找对象数组:

-(NSArray*)findObjectsWithFlag:(BOOL)f{
    NSMutableArray* arr = [NSMutableArray array];
    for (MyObject* obj in _myArray){
        if(obj.flag == f)
            [arr addObject:obj];
    }
    return arr;
}
Run Code Online (Sandbox Code Playgroud)

- 编辑 -

幸运的是,在第一种情况下,我正在寻找的对象有一个唯一的标识符,我知道只有一个.我想出了一个解决方案,在我的对象上实现isEqual,它将被调用indexOfObject:

- (BOOL)isEqual:(id)object{
    return [self.uuid isEqualToString: ((MyObject*)object).uuid];
}
Run Code Online (Sandbox Code Playgroud)

然后创建一个"假的"查找对象,并使用它来查找真实的查找对象

MyObject *lookupObject = [[MyObject alloc] init];
lookupObject.uuid = searchUUID;
MyObject *actualObject = 
    [_myArray objectAtIndex:[_myArray indexOfObject:lookupObject]];
Run Code Online (Sandbox Code Playgroud)

这与我上面发布的for-in循环基本相同,但可能更具可读性和更可重用性.当然,这只适用于找到一个独特的对象,而不是解决我问题的后半部分.

- 编辑2 -

按照评论中的建议检查Class和实施hash.

- (BOOL)isEqual:(id)object{
    return [object isKindOfClass:[MyObject class]] && 
           [self.uuid isEqualToString: ((MyObject*)object).uuid];
}

- (NSUInteger)hash{
    return [self.uuid hash];
}
Run Code Online (Sandbox Code Playgroud)

Mac*_*tle 39

您可以使用[NSPredicate],它为您提供类似查询的搜索语法.查看此页面以获取谓词语法描述.这是一个简单的例子:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"propertyName == %@", @"value"];
NSArray *filteredArray = [myArray filteredArrayUsingPredicate:predicate];
Run Code Online (Sandbox Code Playgroud)

至于性能,我认为您的解决方案是可以的,因为数组中的任何搜索都需要遍历所有元素,然后,对于每个对象,将字段的值与您搜索的值进行比较.您可以在同一数据中优化重复搜索,例如,通过创建和填充将某些字段的值映射到匹配对象(或对象集合,如果映射是一对多)的字典.


vor*_*max 14

您还可以查看现代块语法:indexOfObjectWithOptions:passingTest:或者indexesOfObjectsWithOptions:passingTest:支持并发和搜索顺序.


Szy*_*zur 10

我被rmaddys评论所吸引,所以我检查了循环和谓词之间的区别.

让我们假设一个带有NSString属性的简单对象.我已经将它插入阵列10 000次,每次都有不同的属性值.

在最坏的情况下,当所需对象位于阵列的最后位置时,循环方法比NSPredicate快3.5倍(0.39s vs 0.11s,arraySize = 10000,10次迭代,iPad Mini)

代码我用作参考:pastebin