2016-12-27 60 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