Array.reduce不能通过下标赋值:'x'是'let'常量

时间:2017-10-16 12:56:49

标签: arrays swift

我正在尝试在数组上使用reduce函数:

var fields = ["gender", "name", "nickname"]
var stats = fields.reduce([String:String]()) { (res, field) -> [String:String] in
  res[field] = json[field] ?? ""
  return res
}

它只是通过fields数组并将json对象的值赋给res

对我来说似乎很简单,但编译器一直在说:

  

错误:无法通过下标分配:'res'是'let'常量

就行:

res[field] = json[field] ?? ""

这对我没有任何意义,因为我从未将resstats指定为let

2 个答案:

答案 0 :(得分:9)

闭包参数(除非用inout声明)是隐式常量,就像用let声明一样。 如果你想修改它,那么你必须先制作可变副本:

let stats = fields.reduce([String:String]()) { (res, field) -> [String:String] in
    var res = res
    res[field] = json[field] ?? ""
    return res
}

Swift 4 开始,您可以使用reduce(into:_:)

let stats = fields.reduce(into: [String:String]()) { (res, field) in
    res[field] = json[field] ?? ""
}

此处res是" inout"参数可以在闭包中变异。 这样效率更高,因为每个都没有制作副本 迭代步骤。

另见SE-0171 Reduce with inout

一个不同的Swift 4解决方案是创建一个新词典 通过将每个字段映射到键/值对:

let stats = Dictionary(uniqueKeysWithValues: fields.map { ($0, json[$0] ?? "") })

答案 1 :(得分:2)

在Swift参数中是不可变的,你不能改变作为参数接收的字典

res[field] = json[field] ?? ""

解决方案

let json: [String:Any] = ...
let fields = ["gender", "name", "nickname"]
let stats = fields.reduce([String:String]()) { (res, field) -> [String:String] in
    var res = res
    res[field] = (json[field] as? String) ?? ""
    return res
}