將滿足某條件的東西全部移除的 removeAll(where:) — Swift 4.2

Swift 4.2 多了function removeAll(where:),方便我們將滿足某條件的東西從 array 移除。這有什麼好呢 ?

讓我們先看看 removeAll(where:) 不存在時,一個很容易讓程式閃退的 for 寫法。在 roles array 裡有三個彼得潘故事的角色,好人彼得潘和壞人虎克跟鱷魚。我們希望童話故事裡只有好人,就像光良唱的,幸福和快樂是結局,所以我們利用 for 找出 array 裡 isGood 等於 false 的壞人,將他們從 array 移除。

struct Role {   var name: String   var isGood: Bool}var roles = [Role(name: "彼得潘", isGood: true), Role(name: "虎克", isGood: false), Role(name: "鱷魚", isGood: false)]for (i, role) in roles.enumerated() {   if role.isGood == false {      roles.remove(at: i)   }}

然而程式卻閃退了。因為當我們要移除鱷魚時,array 已經因為之前移除虎克,數量變成 2,但鱷魚對應的 i 是 2,超過 array 成員的數量,造成 Index out of range。

此問題當然有方法可以解決,比方如以下例子利用 function filter 依序對 array 的成員執行參數 closure 的程式,回傳 true 的成員將組合成新的 array。

roles = roles.filter { (role) -> Bool in   return role.isGood}

雖然此方法的結果是正確的,但有一些缺點。它的效能比較差,因為要產生一個新的 array。我們想要的只是把東西從原本的 array 移除,有那麼難嗎 ?

Swift 聽到了我們的心聲,在 4.2 發明 removeAll(where:) 幫助我們。

mutating func removeAll(where predicate: (Role) throws -> Bool) rethrows

removeAll 會依序對 array 的成員執行參數 closure 的程式,當回傳 true 時即代表此成員會被移除。因此在以下例子,壞人們都會被移除,只有好人可以繼續活在 array 裡。

roles.removeAll { (role) -> Bool in   let isRemove = role.isGood == false   return isRemove}

SE-0197 Adding in-place removeAll(where:) to the Standard Library

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com