Swift 2.2 (3.0) 中的地图修改对象数组

Map modify array of objects in Swift 2.2 (3.0)

我希望能够使用 Swift 中的 map 修改我的对象数组,而不用遍历每个元素。

在此之前我们可以做这样的事情(有更详细的描述here:

gnomes = gnomes.map { (var gnome: Gnome) -> Gnome in
    gnome.age = 140
    return gnome
}

感谢 Erica Sadun 和其他人,新提案已经通过,我们现在正在摆脱 C 风格的循环并在循环内使用 var

在我的例子中,我首先收到删除 var 的警告,然后是一个错误,我的 gnome 是一个常量(自然)

我的问题是:我们如何更改 map 中的数组或新样式的循环以便为 Swift 3.0 做好充分准备?

(下面是 Gnome 是引用类型的情况;a class -- 因为您还没有向我们展示您是如何定义 Gnome。对于 Gnome 作为值类型(结构)的情况,请参阅@vadian:s answer)


移除 var 不会影响使用 .map 来改变 reference[=32= 数组的 mutable 成员] 类型的对象。也就是说,您可以简单地使用您的旧方法(但是省略 .map 闭包签名中的 var)。

class Gnome {
    var age = 42
}

var gnomes = [Gnome(), Gnome(), Gnome()]

gnomes = gnomes.map {
    [=10=].age = 150
    return [=10=]
}

/* result */
gnomes.forEach { print([=10=].age) } // 3x 150

但是,如果您只想修改原始数组而不是将 .map 的结果分配给新数组,则 .forEach 可能比 .map 更合适.

gnomes.forEach { [=11=].age = 140 }

/* result */
gnomes.forEach { print([=11=].age) } // 3x 140

如果您想保留该语法,只需使用一个(可变的)临时变量

gnomes = gnomes.map { (gnome: Gnome) -> Gnome in
  var mutableGnome = gnome
  mutableGnome.age = 140
  return mutableGnome
}

鉴于:

struct Gnome {
    var age: Int = 0
}

var gnomes = Array(count: 5, repeatedValue: Gnome())

...有两个不错的选择。第一个是@vadian 所说的:

gnomes = gnomes.map{
    var gnome = [=11=]
    gnome.age = 70
    return gnome
}

而第二个控制 "ageing" private 并简化调用点的映射:

struct Gnome {
    private(set) var age: Int = 0

    func aged(age: Int) -> Gnome {
        var gnome = self
        gnome.age = age
        // any other ageing related changes
        return gnome
    }
}

gnomes = gnomes.map{ [=12=].aged(140) }

当然,引用类型在编程中仍然占有一席之地,在这种情况下可能更合适。我们在这里遇到的摩擦表明我们正试图将这些结构视为物体。如果那是您需要的行为,那么您应该考虑将 Gnome 实现为 class.