更新通过引用传递的数组中的项

时间:2016-12-27 20:07:01

标签: arrays swift swift2 pass-by-reference inout

更新数组中项目的最简单/最正确的方法是什么?我希望调用者也有更新的数组。所以:

text.range(of: "\"")

我希望调用者拥有更新的项目(使用更新的项目)。我认为上面代码的问题是它只更新局部变量项。实际更新items数组中相关项的最佳方法是什么?

2 个答案:

答案 0 :(得分:4)

你这样做的方式与超人穿上紧身裤一样 - 一次一条腿。循环访问传入的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
}

请注意,这是Swift 3语法,其中inout位于类型之前,而不是标签。

您可以使用map

将其写得更加“Swiftily”
func updateItem(updatedItem: Item, items: inout [Item]) {
    items = items.map {
        $0.id == updatedItem.id ? updatedItem : $0
    }
}

......但这最终会成为同样的事情。

答案 1 :(得分: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 matching 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
}