ios – 从Objective-C中的数组中删除一个项目

这个问题可能看起来很容易,但我正在寻找最有效率和记忆友好的方式。

假设我有一个Person对象数组。每个人都有由NSString代表的头发颜色。我们来说,我想从数组中删除所有的Person对象,他们的头发颜色是棕色的。

我该如何做?

请记住,您不能从被枚举的数组中删除对象。

最佳答案
有两种一般方法。我们可以测试每个元素,然后立即删除元素,如果满足测试条件,或者我们可以测试每个元素并存储符合测试条件的元素的索引,然后一次删除所有这些元素。对于内存使用是一个真正的问题,对后一种方法的存储要求可能会使其不可取。

通过“存储要删除的所有索引,然后删除它们”的方法,我们需要考虑前一种方法中涉及的细节,以及它们如何影响方法的正确性和速度。在这种方法中有两个致命的错误。第一个是删除被评估的对象不是基于其在数组中的索引,而是使用removeObject:方法。 removeObject:对数组进行线性搜索以查找要删除的对象。使用大的未排序的数据集,这将随着输入大小的平方随时间的增加而破坏我们的性能。顺便说一下,使用indexOfObject:然后removeObjectAtIndex:也是一样糟糕,所以我们也应该避免它。第二个致命错误将在索引0开始迭代。NSMutableArray在添加或删除对象后重新排列索引,所以如果我们从索引0开始,我们将保证一个索引超出边界异常,如果一个对象在迭代。所以,我们必须从数组的后面开始,只删除索引低于目前为止所检查的每个索引的索引。

确定了这一点,真的有两个明显的选择:一个for循环,从结尾而不是数组的开始,或NSArray方法enumerateObjectsWithOptions:usingBlock:method开始。每个例子如下:

[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];
    }
}

我的测试似乎显示了for循环的速度更快 – 对于50万个元素来说可能要快四分之一秒,基本上是8.5和8.25秒之间的差异。所以我建议使用块方法,因为它更安全,感觉更为惯用。

转载注明原文:ios – 从Objective-C中的数组中删除一个项目 - 代码日志