基本问题。在Swift中有选择地从可变数组中删除和删除项目的最佳方法是什么?
有些选项似乎不适合这样做,比如在
中调用 removeObject和其他似乎一般工作的人
是否有推荐的,简单而安全的方法从阵列中删除项目?其中一个我提到的或我失踪的东西?
获得不同的(有利有弊)或偏好是很好的。我仍然很难选择合适的人。
答案 0 :(得分:11)
如果要根据条件循环并从NSMutableArray
中删除元素,可以按相反的顺序循环数组(从最后一个索引到零),并删除满足条件的对象。
例如,如果你有一个整数数组,想要删除可被3整除的数字,你可以像这样运行循环:
var array: NSMutableArray = [1, 2, 3, 4, 5, 6, 7];
for index in stride(from: array.count - 1, through: 0, by: -1) {
if array[index] as Int % 3 == 0 {
array.removeObjectAtIndex(index)
}
}
以相反顺序循环可确保仍要检查的数组元素的索引不会更改。相反,在正向模式下,如果删除第一个元素,那么之前在索引1处的元素将更改为索引0,并且您必须在代码中考虑该元素。
出于性能原因,不建议在循环中使用removeObject
(不能使用上面的代码),因为它的实现遍历数组的所有元素并使用isEqualTo
来确定是否删除对象。复杂性顺序从O(n)升高到O(n ^ 2) - 在最坏的情况下,数组的所有元素都被移除,数组在主循环中遍历一次,并且再次遍历每个元素。阵列。因此,除非您有充分的理由,否则应避免使用基于枚举块for-in
等的所有解决方案。
filter
反而是一个很好的选择,而这正是我使用的原因:
但在所有情况下,它可能并不理想,因为正如您所说,它会生成一个新数组,而不是在适当的位置运行。
答案 1 :(得分:7)
使用NSMutableArray时,在循环可变数组本身时不应删除对象(除非向后循环,如Antonio的答案所指出的那样)。
一个常见的解决方案是创建数组的不可变副本,迭代副本,并通过调用“removeObject”或调用“removeObjectAtIndex”在原始可变数组上有选择地删除对象,但是您必须计算索引,因为原始数组中的索引和副本因删除而不匹配(每次删除对象时都必须减少“删除索引”)。
另一个解决方案(更好)是循环数组一次,创建一个NSIndexSet,其中包含要删除的对象的索引,然后在可变数组上调用“removeObjectsAtIndexes:”。
See documentation on NSMutableArray's "removeObjectsAtIndexes:" in Swift
答案 2 :(得分:4)
部分选项:
removeObjectAtIndex
:1)您必须处理以下事实:当您删除时,以下对象的索引将成为当前索引,因此您必须确保不在这种情况下递增索引;你可以通过向后迭代来避免这种情况。 2)对removeObjectAtIndex
的每次调用都是O(n)(因为它必须向前移动所有后续元素),因此算法为O(n ^ 2)。removeObjectsInArray
的元素:第一部分是O(n)。 removeObjectsInArray
使用哈希表来有效地测试要删除的元素;哈希表访问平均为O(1),但O(n)最坏情况,因此算法平均为O(n),但O(n ^ 2)最坏情况。filter
创建新数组:这是O(n)。它创建了一个新数组。indexesOfObjectsPassingTest
),然后使用removeObjectsAtIndexes
删除它们:我相信这是O(n)。它不会创建新阵列。filterUsingPredicate
:我相信这也是O(n)。它不会创建新阵列。