2016-12-27 61 views
2

更新數組中項目的最簡單/正確的方法是什麼?我希望調用者也有更新的數組。所以:更新通過引用傳遞的數組中的項目

static func updateItem(updatedItem: Item, inout items: [Item]) -> Bool { 
     var item = items.filter{ $0.id == updatedItem.id }.first 
     if item != nil { 
      item = updatedItem 
      return true 
     } 

     return false 
    } 

我想調用者有更新的項目(與更新的項目)。我認爲上述代碼的問題是它只更新本地變量項目。實際更新items數組中的相關項目的最佳方式是什麼?

+0

如果不存在具有相同'id'的現有項目,那麼您希望如何更新'updatedItem'? – Alexander

回答

3

你這樣做超人進入他的緊身衣 - 一次一個腿。通過傳入inout陣列週期並更換任何產品,其中id匹配:

func updateItem(updatedItem: Item, items: inout [Item]) -> Bool { 
    var result = false 
    for ix in items.indices { 
     if items[ix].id == updatedItem.id { 
      items[ix] = updatedItem 
      result = true 
     } 
    } 
    return result 
} 

注意,這是夫特3語法,其中inout之前的類型,而不是標籤。

您可以通過使用map寫多一點「Swiftily」:

func updateItem(updatedItem: Item, items: inout [Item]) { 
    items = items.map { 
     $0.id == updatedItem.id ? updatedItem : $0 
    } 
} 

...但是,這相當於在年底同樣的事情。

+0

我正在返回bool,因爲調用者會根據是否找到項目來做一些額外的事情。如果在「快速」方法中找不到項目,我該如何返回錯誤? – Prabhu

+0

我重寫了第一種返回Bool的方法,我建議你使用它。使用第二種方法沒有節省 - 「地圖」仍然是一個循環。 – matt

2

您突變item,其僅僅是實例的陣列中的複製(如果Item爲值類型,諸如structtuple,或者enum),或它的一個引用(如果Item是引用類型,比如`class)。無論哪種情況,陣列都不會受到影響。

您需要在數組中找到實例的索引,然後改變該索引處的數組。

func updateItem(updatedItem: Item, inout items: [Item]) -> Bool { 
    guard let index = items.index(where: { $0.id == updatedItem.id }) else { 
     return false // No mathching item found 
    } 

    items[index] = updatedItem 
    return true 
} 

雖然這一切都很笨重。如果您使用字典,將會更好,將id映射到具有該id的實例。這意味着你將有快速,持續的時間查詢,而且會更方便。下面是它的外觀:

// Assuming the "id" is an Int 
func updateItem(updatedItem: Item, items: inout [Int: Item]) -> Bool { 
    return items.updateValue(updatedItem, forKey: updatedItem.id) != nil 
} 
+0

謝謝,與字典將如何調用代碼看起來? – Prabhu

+1

同樣,你只是通過新項目和所有項目的字典 – Alexander

+0

嗯,它是說類型[Item]的值沒有成員索引。 – Prabhu