2014-09-06 92 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