【问题标题】:Map modify array of objects in Swift 2.2 (3.0)在 Swift 2.2 (3.0) 中映射修改对象数组
【发布时间】:2016-03-28 11:50:06
【问题描述】:

我希望能够在 Swift of the fly 中使用 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 做好充分准备?

【问题讨论】:

    标签: arrays swift map-function


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      (下面是Gnome 是引用类型的情况;一个类——因为你没有向我们展示你是如何定义Gnome 的。对于Gnome 作为值类型的情况(一个结构),见@vadian:s 答案)


      删除var 不会影响使用.map 来改变reference 类型对象数组的可变 成员。即,您可以简单地使用旧方法(但是,在 .map 闭包签名中省略 var)。

      class Gnome {
          var age = 42
      }
      
      var gnomes = [Gnome(), Gnome(), Gnome()]
      
      gnomes = gnomes.map {
          $0.age = 150
          return $0
      }
      
      /* result */
      gnomes.forEach { print($0.age) } // 3x 150
      

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

      gnomes.forEach { $0.age = 140 }
      
      /* result */
      gnomes.forEach { print($0.age) } // 3x 140
      

      【讨论】:

      • 返回错误$0 is immutable。这是我的错。我应该更精确:(我使用的是结构而不是类,我敢打赌是什么使它们默认不可变
      • @kernelpanic 由于您没有向我们展示Gnome 课程,因此我必须包括我自己的一个。您确定您的班级的 age 属性是可变的(以及您的 gnome 数组)吗?以上对我来说适用于 Swift 2.2 和 Xcode 7.3。
      • @dfri 我怀疑Gnome 是一个结构体
      • 赞成引用 .forEach() 这就是我想要的。
      • @jan.vogt 乐于提供帮助。
      【解决方案3】:

      给定:

      struct Gnome {
          var age: Int = 0
      }
      
      var gnomes = Array(count: 5, repeatedValue: Gnome())
      

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

      gnomes = gnomes.map{
          var gnome = $0
          gnome.age = 70
          return gnome
      }
      

      虽然第二个可以控制“老化”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{ $0.aged(140) }
      

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

      【讨论】:

        猜你喜欢
        • 2022-06-17
        • 1970-01-01
        • 2015-04-11
        • 1970-01-01
        • 2016-11-22
        • 2018-08-18
        • 1970-01-01
        • 1970-01-01
        • 2020-09-18
        相关资源
        最近更新 更多