2015-04-16 67 views
5

我有對象的一個​​這樣的數組:從對象數組中刪除匹配的項目?

var myArr = [ 
    MyObject(name: "Abc", description: "Lorem ipsum 1."), 
    MyObject(name: "Def", description: "Lorem ipsum 2."), 
    MyObject(name: "Xyz", description: "Lorem ipsum 3.") 
] 

我知道我能找到這樣的匹配項:

var temp = myArr.filter { $0.name == "Def" }.first 

但是現在我如何從原來的myArr去除呢?我希望filter.first可以返回索引,所以我可以使用removeAtIndex。或者更好的是,我想這樣做:

myArr.removeAll { $0.name == "Def" } // Pseudo 

任何想法?

+2

'myArr = myArr.filter {$ 0.name!=「Def」}''有什麼問題? – matt

+0

因爲這迫使我創建一個新的變量。我想修改現有的'myArr'變量。 – TruMan1

+0

不,它不。 'myArr'仍然是'myArr'。這是一種價值類型;你不能改變它!即使你寫了一個突變的removeAll方法,你也會創建一個新的數組。 – matt

回答

11

你不抓是什麼陣是一個結構,因此是值類型。它不能按照類實例的方式進行變異。因此,即使您將Array擴展爲編寫變異的方法,您也將始終在幕後創建新的數組。

因此存在使用filter沒有缺點,也沒有一般性的損失和你的閉合狀態的邏輯負:

myArr = myArr.filter { $0.name != "Def" } 

例如,您可以removeIf這樣的:

extension Array { 
    mutating func removeIf(closure:(T -> Bool)) { 
     for (var ix = self.count - 1; ix >= 0; ix--) { 
      if closure(self[ix]) { 
       self.removeAtIndex(ix) 
      } 
     } 
    } 
} 

然後你可以像這樣使用它:

myArr.removeIf {$0.name == "Def"} 

但事實上,這是一個浪費時間的巨大浪費。你在這裏什麼都沒做,filter還沒有做。它可能出現myArr.removeIf語法,你正在突變myArr到位,但你不是;你正在用另一個數組替換它。確實,調用removeAtIndex在該循環中創建另一個數組!所以你不妨使用filter並很開心。

+0

這是「正確的」答案。如果你想了解它是如何工作的,那麼看看我的。瞭解這一點對於如何過濾和更重要!=工作至關重要。這只是說「將所有對象留在這個數組中,除非它匹配」Def「」。 –

+0

我已經更新了我的答案以顯示實際的'removeIf'實現。所以如果你真的想要的話,你可以擴展Array來使其成爲一種變異的方法。但是,正如我也指出的那樣,這樣的做法將毫無意義。 – matt

+0

'mutating func removeAtIndex()'真的創建一個新的數組嗎? –

1

使用篩選器獲取對象,然後遍歷數組並使用myArr.removeAtIndex(index)刪除每個對象。使用過濾器就是這樣做的。瞭解下面的內容。由於您正在測試相反的匹配,因此每個對象都會被保留,除非它符合您的值,否則Matts答案是一種更簡潔的方法來完成此操作。

遍歷您的臨時濾波器陣列

if let index = find(temp, note) { 
    myArr.removeAtIndex(index) 
} 
+0

For循環找到索引的唯一方法是什麼?是否有一個優雅的封閉? – TruMan1

+0

'find'只適用於簡單的數組,而不是對象數組?無法使用'find'來處理對象數組。 – TruMan1

+0

您已經使用過濾器獲取了所有對象,然後您可以在循環中使用find從每個數組中刪除每個對象。 –

1

,如果你想從正在迭代的數組中刪除一個對象,你應該總是向後遍歷否則你會在那些不再有效的索引一些點的工作。

var myArr = [ 
    ["key":"value1"], 
    ["key":"value2"], 
    ["key":"value3"] 
] 

for index in stride(from: myArr.count - 1 , to: 0, by: -1){ 
    let x = myArr[index] 
    if x["key"] == "value2"{ 
     myArr.removeAtIndex(index) 
    } 
}