Cho*_*oli 21 objective-c nsstring nsmutablearray nsarray ios
这个问题看似简单,但我正在寻找最有效和最友好的方式.
假设我有一个Person对象数组.每个人都有一个由头发颜色代表的头发颜色NSString.然后我们说我想从数组中删除头发颜色为棕色的所有Person对象.
我该怎么做呢?
请记住,您无法从枚举的数组中删除对象.
Car*_*zey 28
有两种一般方法.我们可以测试每个元素,然后在符合测试标准的情况下立即删除元素,或者我们可以测试每个元素并存储符合测试条件的元素的索引,然后立即删除所有这些元素.由于存储器使用是一个真正的问题,后一种方法的存储要求可能使其不合需要.
通过"存储所有要删除的索引,然后删除它们"的方法,我们需要考虑前一种方法中涉及的细节,以及它们将如何影响方法的正确性和速度.在这种方法中有两个致命的错误等待.第一种方法是删除不是基于数组中索引的计算对象,而是使用removeObject:方法.removeObject:对数组进行线性搜索以找到要删除的对象.对于大的未分类的数据集,随着时间随着输入大小的平方而增加,这将破坏我们的性能.顺便说一句,使用indexOfObject:然后removeObjectAtIndex:就是那么糟糕,所以我们也应该避免它.第二个致命错误是在索引0处开始我们的迭代.NSMutableArray在添加或删除对象后重新排列索引,因此如果我们从索引0开始,如果在迭代期间删除了一个对象,我们将保证索引超出范围异常.因此,我们必须从数组的后面开始,并且只删除索引低于我们到目前为止检查的每个索引的对象.
实现这一目标后,实际上有两个明显的选择:for从最后开始而不是数组开始的循环,或NSArray方法enumerateObjectsWithOptions:usingBlock:方法.每个例子如下:
[persons enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(Person *p, NSUInteger index, BOOL *stop) {
if ([p.hairColor isEqualToString:@"brown"]) {
[persons removeObjectAtIndex:index];
}
}];
NSInteger count = [persons count];
for (NSInteger index = (count - 1); index >= 0; index--) {
Person *p = persons[index];
if ([p.hairColor isEqualToString:@"brown"]) {
[persons removeObjectAtIndex:index];
}
}
Run Code Online (Sandbox Code Playgroud)
我的测试似乎表明for循环速度略快 - 对于500,000个元素来说可能快了大约四分之一秒,这基本上是8.5到8.25秒之间的差异.所以我建议使用块方法,因为它更安全,感觉更惯用.
Rob*_*Rob 14
假设您正在处理一个可变数组并且它没有被排序/索引(即您必须扫描数组),您可以使用enumerateObjectsWithOptions以下NSEnumerationReverse选项以相反的顺序迭代数组:
[array enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
// now you can remove the object without affecting the enumeration
}];
Run Code Online (Sandbox Code Playgroud)
通过以相反的顺序,您可以从枚举的数组中删除一个对象.
NSMutableArray * tempArray = [self.peopleArray mutableCopy];
for (Person * person in peopleArray){
if ([person.hair isEqualToString: @"Brown Hair"])
[tempArray removeObject: person]
}
self.peopleArray = tempArray;
Run Code Online (Sandbox Code Playgroud)
或NSPredicate也有效:http://nshipster.com/nspredicate/
关键是使用谓词过滤数组。看下面的代码;
- (NSArray*)filterArray:(NSArray*)list
{
return [list filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings){
People *currentObj = (People*)evaluatedObject;
return (![currentObj.hairColour isEqualToString:@"brown"]);
}]];
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
47590 次 |
| 最近记录: |