Dictionary 的序列初始化器
在 Swift 4 中,假设键保证是唯一的,你可以简单地说:
let array = [MyStruct(key: 0, value: "a"), MyStruct(key: 1, value: "b")]
let dict = Dictionary(uniqueKeysWithValues: array.lazy.map { ($0.key, $0.value) })
print(dict) // [0: "a", 1: "c"]
这是使用来自SE-0165 的init(uniqueKeysWithValues:) 初始化程序。它需要一个键值元组序列,其中的键保证是唯一的(如果不是,你会得到一个致命错误)。因此,在这种情况下,我们将对数组中的元素应用惰性转换,以获得键值对的惰性集合。
如果键不保证是唯一的,您将需要某种方法来决定将哪些可能的值用于给定键。为此,您可以使用 init(_:uniquingKeysWith:) 初始化程序 from the same proposal,并传递给定函数以确定在出现重复键时为给定键使用哪个值。
uniquingKeysWith: 函数的第一个参数是字典中已经存在的值,第二个是试图插入的值。
例如,这里每次在序列中出现重复键时,我们都会覆盖该值:
let array = [MyStruct(key: 0, value: "a"), MyStruct(key: 0, value: "b"),
MyStruct(key: 1, value: "c")]
let keyValues = array.lazy.map { ($0.key, $0.value) }
let dict = Dictionary(keyValues, uniquingKeysWith: { _, latest in latest })
print(dict) // [0: "b", 1: "c"]
要保留给定键的第一个值,并忽略同一键的任何后续值,您需要{ first, _ in first } 的uniquingKeysWith: 闭包,在这种情况下给出[0: "a", 1: "c"] 的结果。
使用inout 累加器减少
在 Swift 4 中,另一个可能的选项是使用 reduce(into:_:),在 SE-0171 中引入,假设您希望通过覆盖每次出现给定键的值来合并任何重复键。
与reduce(_:_:) 不同,此方法使用inout 参数作为组合函数中的累加器。这允许它避免在填充字典累加器时在reduce(_:_:) 的每次迭代中发生不必要的累加器复制。因此,这允许我们以线性时间而不是二次时间来填充它。
你可以这样使用它:
let array = [MyStruct(key: 0, value: "a"), MyStruct(key: 0, value: "b"),
MyStruct(key: 1, value: "c")]
let dict = array.reduce(into: [:]) { $0[$1.key] = $1.value }
print(dict) // [0: "b", 1: "c"]
// with initial capacity to avoid resizing upon populating.
let dict2 = array.reduce(into: Dictionary(minimumCapacity: array.count)) { dict, element in
dict[element.key] = element.value
}
print(dict2) // [0: "b", 1: "c"]