迭代时从NSMutableArray中移除的最佳方法是什么?
在Cocoa中,如果我想循环遍历一个NSMutableArray并删除符合特定条件的多个对象,那么每次删除一个对象时,如何在不重新启动循环的情况下执行此操作,最好的方法是什么?
谢谢,
编辑:只是为了澄清 - 我正在寻找最好的方式,例如比手动更新索引更优雅的东西。 例如在C ++中,我可以做;
iterator it = someList.begin();
while (it != someList.end())
{
if (shouldRemove(it))
it = someList.erase(it);
}
为了清楚起见,我喜欢在收集要删除的项目时进行初始循环。 然后我删除它们。 以下是使用Objective-C 2.0语法的示例:
NSMutableArray *discardedItems = [NSMutableArray array];
for (SomeObjectClass *item in originalArrayOfItems) {
if ([item shouldBeDiscarded])
[discardedItems addObject:item];
}
[originalArrayOfItems removeObjectsInArray:discardedItems];
那么,索引是否正确更新,或其他小簿记细节是没有问题的。
编辑添加:
在其他答案中已经指出,逆配方应该更快。 即如果你遍历数组,并组成一个新的数组对象来保持,而不是丢弃对象。 这可能是真的(尽管分配新阵列的内存和处理成本以及丢弃旧阵列的成本如何?),但即使速度更快,它可能不会像原先的实现那么大,因为NSArrays不像“正常”阵列。 他们谈论这个谈话,但他们走了另一条路。 在这里看到一个好的分析:
逆配方可能会更快,但我从来不需要关心它是否是因为上述公式一直足以满足我的需求。
对我来说,回家的信息是使用任何最明确的表达方式。 只在必要时进行优化。 我个人认为上述表述最清楚,这就是我使用它的原因。 但是如果反面的表述对你更清楚,那就去做吧。
还有一个变种。 所以你得到可读性和良好的性能:
NSMutableIndexSet *discardedItems = [NSMutableIndexSet indexSet];
SomeObjectClass *item;
NSUInteger index = 0;
for (item in originalArrayOfItems) {
if ([item shouldBeDiscarded])
[discardedItems addIndex:index];
index++;
}
[originalArrayOfItems removeObjectsAtIndexes:discardedItems];
其他一些答案在非常大的数组上的性能很差,因为像removeObject:
和removeObjectsInArray:
这样的方法涉及到对接收器进行线性搜索,这很浪费,因为您已经知道对象在哪里。 此外,对removeObjectAtIndex:
任何调用都必须removeObjectAtIndex:
将索引中的值复制到阵列的末尾一个位置。
效率更高的是以下几点:
NSMutableArray *array = ...
NSMutableArray *itemsToKeep = [NSMutableArray arrayWithCapacity:[array count]];
for (id object in array) {
if (! shouldRemove(object)) {
[itemsToKeep addObject:object];
}
}
[array setArray:itemsToKeep];
因为我们设置了itemsToKeep
的容量, itemsToKeep
我们不会浪费任何时间在调整大小时复制值。 我们不修改数组,所以我们可以自由使用快速枚举。 使用setArray:
用itemsToKeep
替换array
的内容将是高效的。 根据你的代码,你甚至可以用最后一行代替:
[array release];
array = [itemsToKeep retain];
所以甚至不需要复制值,只需交换一个指针。
链接地址: http://www.djcxy.com/p/85143.html上一篇: Best way to remove from NSMutableArray while iterating?