【问题标题】:Updating an item in an array passed by reference更新通过引用传递的数组中的项目
【发布时间】:2017-05-12 02:48:12
【问题描述】:

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

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 数组中相关项目的最佳方法是什么?

【问题讨论】:

  • 如果没有具有相同id 的现有项目,您想对updatedItem 做什么?

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


【解决方案1】:

你这样做的方式与超人穿紧身衣的方式相同——一次一条腿。循环遍历传入的 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写得更“迅速”:

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

...但最终结果是一样的。

【讨论】:

  • 我返回 bool 是因为调用者根据是否找到项目做了一些额外的事情。如果在您的“迅速”方法中找不到项目,我该如何返回 false?
  • 我重写了第一个返回 Bool 的方法,我建议你使用它。使用第二种方法没有节省 - map 仍然是一个循环。
【解决方案2】:

您正在改变item,它只是数组中实例的副本(如果Item 是值类型,例如structtupleenum),或引用到它(如果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
}

【讨论】:

  • 谢谢,有了字典,调用代码会怎样?
  • 同理,传入新项目和所有项目的dict
  • 嗯,是说 [Item] 类型的值没有成员索引。
  • @Prabhu 我认为 Swift 2 中不存在这样的功能。您可以在 Sequence 上编写扩展来自己添加它,但实际上,只需使用 Swift 3
  • 嗯,是的,问题是我们还没有准备好迁移到 Swift 3,所以我猜得做扩展。
猜你喜欢
  • 2015-06-10
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-09
  • 2012-11-05
  • 1970-01-01
相关资源
最近更新 更多