I'm trying to use the reduce
function on an array:
var fields = ["gender", "name", "nickname"]
var stats = fields.reduce([String:String]()) { (res, field) -> [String:String] in
res[field] = json[field] ?? ""
return res
}
It's just going through the fields
array and assigns values from json object to res
.
Seems simple to me but the compiler keeps saying:
error: cannot assign through subscript: 'res' is a 'let' constant
on the line:
res[field] = json[field] ?? ""
It doesn't make any sense to me because I've never specified res
or stats
as let
.
Closure parameters (unless declared with inout
) are implicitly constants, as if declared with let
.
If you want to modify it then you have to make mutable copy first:
let stats = fields.reduce([String:String]()) { (res, field) -> [String:String] in
var res = res
res[field] = json[field] ?? ""
return res
}
As of Swift 4 you can use reduce(into:_:)
:
let stats = fields.reduce(into: [String:String]()) { (res, field) in
res[field] = json[field] ?? ""
}
Here res
is an "inout" parameter and can be mutated in the closure.
This is far more efficient, because no copies are made in each
iteration step.
See also SE-0171 Reduce with inout.
A different Swift 4 solution would be create a new dictionary by mapping each field to a key/value pair:
let stats = Dictionary(uniqueKeysWithValues: fields.map { ($0, json[$0] ?? "") })
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With