2014-09-06 54 views
5

基本问题。什么是有选择地从Swift中的可变数组中删除和删除项目的最佳方法?有选择地从Swift中的NSMutableArray中删除和删除对象

有迹象表明,似乎并不以适合于这个喜欢在循环中调用的removeObject

  • 的选项
  • 枚举块

和其他人似乎工作,一般像

  • 用于使用索引+调用removeObjectAtIndex,即使是循环
  • 用于循环用于填充一个arrayWithItemsToRemove,然后使用originalArray内部。 removeObjectsInArray
  • 使用.filter创建一个新的阵列(arrayWithItemsToRemove)似乎是非常好的,但我不能肯定我的感觉有关更换整个原始阵列

是否有推荐,从数组中删除项目的简单而又安全的方法?其中一个我提到的或我失踪的东西?

这将是很好的获得不同的需要(利与弊)或偏好。我仍然努力选择正确的。

+0

你在说Swift的数组吗?或关于NSMutableArray? – George 2014-09-06 12:23:57

+1

一个NSMutableArray。感谢您的评论。我改变了标题以澄清这一点。 – Bernd 2014-09-06 12:42:05

回答

7

当你使用NSMutableArray时,你不应该在沿着可变数组本身循环的时候移除对象(除非向后循环,正如Antonio的答案所指出的那样)。

一个常见的解决方案是通过调用“removeObject”或通过调用“removeObjectAtIndex”来创建数组的不可变副本,在副本上进行迭代,并在原始可变数组上选择性地移除对象,但是必须计算索引,因为原数组和副本中的索引因为删除而不匹配(每次删除对象时,您都必须减少“删除索引”)。

另一个解决方案(更好)是循环一次数组,创建一个NSIndexSet,其中包含要删除的对象的索引,然后在可变数组上调用“removeObjectsAtIndexes:”。

See documentation on NSMutableArray's "removeObjectsAtIndexes:" in Swift

11

如果要根据条件从NSMutableArray中循环移除元素,可以按相反顺序(从上一个索引到零)循环数组,并删除满足条件的对象。

举例来说,如果你有一个整数数组,并希望通过三到删除整除的数字,你可以运行这样的循环:

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行代码,而不是基于索引溶液的5行(包括右括号)
  • 它的性能是相当的指标基础的解决方案 - 这是一个慢一点,但我觉得没有那么多

这可能不是,虽然所有的情况下理想的,因为,如你所说,它生成一个新阵列,而不是在现场操作。

+0

而对于Swift 2.0,你会希望'array.removeAtIndex(index)' – Kat 2015-07-24 20:52:41

4

一些选项:

  • 对于环比指标,并呼吁removeObjectAtIndex:1)你将不得不面对这样一个事实,当你删除,以下对象的索引将成为当前指数,所以你必须确保在这种情况下不增加索引;你可以通过向后迭代来避免这种情况。 2)对removeObjectAtIndex的每次调用都是O(n)(因为它必须向前移动所有后续元素),所以算法是O(n^2)。
  • For循环构建一组元素以删除然后调用removeObjectsInArray:第一部分是O(n)。 removeObjectsInArray使用哈希表来有效地测试要移除的元素;哈希表访问平均为O(1),但O(n)最差,因此算法平均为O(n),但O(n^2)最差。
  • 使用filter创建一个新数组:这是O(n)。它创建一个新的数组。
  • For循环建立索引的元素索引集删除(或与indexesOfObjectsPassingTest),然后删除它们使用removeObjectsAtIndexes:我相信这是O(n)。它不创建新的数组。使用基于测试块的谓词使用filterUsingPredicate:我相信这也是O(n)。它不创建新的数组。
+0

这是obj-c方法没有?主题是关于Swift – Vinzius 2015-06-08 09:17:15

+0

@Vinzius:引用的方法是'NSMutableArray'的方法。 'NSMutableArray'是Foundation框架中的一个类,在Objective-C和Swift中都是这样。 – newacct 2015-06-09 00:39:53

+0

确切的说,我的不好。我正在寻找数组方法:-)试图只做swift。 – Vinzius 2015-06-09 12:15:41