ios NSArray 查找一个或多个对象 - 最佳实践

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20024937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 22:24:07  来源:igfitidea点击:

NSArray find object or objects - best practices

iosobjective-cnsarray

提问by Uptown Apps

Solution:I have marked @BlackRider's answer as correct as it is the most versatile especially for complex comparisons however there are other very good answers and comments. I would encourage anyone with the same or similar question to review them and evaluate the best course of action for your specific situation.

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

In my situation, I am actually not using BlackRider's solution in my implementation. I have elected to use my own solution (see Edit #2 below) with help from @JoshCaswell's comments as well as @voromax's suggestion of indexesOfObjectsWithOptions:passingTest:due to the fact that my comparisons are very simple in this situation.

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

Thanks to everyone who answered and provided insight.

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



I am looking for an efficient way to retrieve an object from an NSArraybased on a property of that object (a unique identifier, in this case). In C#.NET using Linq I would do something like

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

MyObject obj = myList.Single(o => o.uuid == myUUID);

I am also wondering if there is an efficient way to get an array of objects matching a non-unique property. Again, with Linq it would look like

我还想知道是否有一种有效的方法来获取与非唯一属性匹配的对象数组。再次,使用 Linq 看起来像

List<MyObject> objs = myList.Where(o => o.flag == true).ToList();

Of course I can write loops to do this but they would not be reusable and I'm suspicious of their performance.

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

Finding an object with a unique ID:

查找具有唯一 ID 的对象:

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

Finding an array of objects:

查找对象数组:

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

-- EDIT --

- 编辑 -

Luckily in the first situation the object I am looking for has a unique identifier and I know there will only be one. I came up with a solution to implement isEqual on my object which will be invoked by indexOfObject:

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

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

And then create a "fake" lookup object and use that to find the real one

然后创建一个“假”查找对象并使用它来找到真正的对象

MyObject *lookupObject = [[MyObject alloc] init];
lookupObject.uuid = searchUUID;
MyObject *actualObject = 
    [_myArray objectAtIndex:[_myArray indexOfObject:lookupObject]];

This is essentially the same as the for-in loop I posted above, but might be more readable & be more reusable. Of course, this only works for finding one unique object and does not address the second half of my question.

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

-- EDIT 2 --

-- 编辑 2 --

Checking Classand implementing hashas recommended in comments.

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

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

- (NSUInteger)hash{
    return [self.uuid hash];
}

回答by Macondo2Seattle

You can use [NSPredicate], which gives you a query-like syntax for search. Check out this pagefor the predicate syntax description. Here's a simple example:

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

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"propertyName == %@", @"value"];
NSArray *filteredArray = [myArray filteredArrayUsingPredicate:predicate];

As to performance, I think your solution is OK since any search in an array needs to iterate through all the elements anyway, and then, for each object, compare the value of a field against the value you search for. You can optimize repeat searches within the same data, e.g. by creating and populating a dictionary that maps values of some field to the matching objects (or collections of objects, if the mapping is one to many).

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

回答by voromax

You may also look at modern block syntax: indexOfObjectWithOptions:passingTest:or indexesOfObjectsWithOptions:passingTest:which support concurrency and search order.

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

回答by Szymon Kuczur

I was intrigued by rmaddys comment so I've checked the difference between looping and predicate.

我对 rmaddys 的评论很感兴趣,所以我检查了循环和谓词之间的区别。

Let's assume a simple object with NSString property. I've inserted it into array 10 000 times , every time with different property value.

让我们假设一个具有 NSString 属性的简单对象。我已将它插入数组 10 000 次,每次都具有不同的属性值。

In the worst case scenario when desired object was on the last position of the array, loop approach was 3.5x faster than NSPredicate (0.39s vs 0.11s, arraySize = 10000, 10 iterations, iPad Mini)

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

Code I used for reference: pastebin

我用于参考的代码:pastebin

回答by RASS

just for those who are interested, I've found the fastest way to search through NSArray is by using a for loop on a background thread. using the [self performSelectorInBackground...] method. In an NSArray of 10000 custom objects I searched through the whole thing thoroughly in around 1 second. On the main thread it took around 10 seconds or more.

对于那些感兴趣的人,我发现搜索 NSArray 的最快方法是在后台线程上使用 for 循环。使用 [self performSelectorInBackground...] 方法。在包含 10000 个自定义对象的 NSArray 中,我在大约 1 秒内彻底搜索了整个内容。在主线程上大约需要 10 秒或更长时间。

回答by Rajan Maheshwari

I know its related with NSArraybut if we do it using Swiftand using the swift Array which is a struct, then that will be lot easier.

我知道它与 with 相关,NSArray但如果我们Swift使用 swift Array来做它struct,那么这会容易得多。

Swift 2.2 / Swift 3.0 / Swift 4.xWorking fine on all versions

Swift 2.2 / Swift 3.0 / Swift 4.x 适用于所有版本

Lets assume we have a custom model class

假设我们有一个自定义模型类

class User {
    var userId = 0
    var userName = ""
} 

And lets assume we have an array named as usersArraywhich has custom objects of Userclass.

让我们假设我们有一个名为 as 的数组,usersArray它具有User类的自定义对象。

And we want to fetch an object from this array with userId = 100for example:-

我们想从这个数组中获取一个对象userId = 100,例如:-

let filteredArray = usersArray.filter({
print(filteredArray[0].userName) //will print the name of the user with userId = 100
.userId == 100})

This filtered array will contain all the custom objects which have userIdas 100

此过滤后的数组将包含所有自定义对象,这些对象具有userId100

##代码##