我有一个键值对数组:
let arr = [(key:"hey", value:["ho"]), (key:"ha", value:["tee", "hee"])]
我将它分成两个数组,如下所示:
let (keys, values) = (arr.map{$0.key}, arr.map{$0.value})
实际上,这与 zip
相反——我将一个元组数组变成两个数组。
但我不喜欢调用 map
两次,因为这意味着我在数组中循环两次。然而,我也不想事先将两个目标数组声明为空数组并在追加时循环一次,例如使用 forEach
。是否有一些很棒的 Swifty 习惯用法可以将我的元组数组解压缩为两个数组?
最佳答案
在 Swift 4 中,你可以使用 reduce(into:)
:
let (keys, values) = arr.reduce(into: ([String](), [[String]]())) {
$0.0.append($1.key)
$0.1.append($1.value)
}
你说:
Yet neither do I want to declare the two target arrays beforehand as empty arrays and loop once while appending, e.g. with
forEach
.
就个人而言,这正是我会做的。我只想编写一个函数来执行此操作(这样您就不会在代码中散布这种模式)。但我认为以下内容比 reduce
模式更清晰、更直观,而且不会受到双重 map
方法效率低下的影响。
/// Unzip an `Array` of key/value tuples.
///
/// - Parameter array: `Array` of key/value tuples.
/// - Returns: A tuple with two arrays, an `Array` of keys and an `Array` of values.
func unzip<K, V>(_ array: [(key: K, value: V)]) -> ([K], [V]) {
var keys = [K]()
var values = [V]()
keys.reserveCapacity(array.count)
values.reserveCapacity(array.count)
array.forEach { key, value in
keys.append(key)
values.append(value)
}
return (keys, values)
}
或者,如果您觉得有必要将其作为扩展
,您也可以这样做:
extension Array {
/// Unzip an `Array` of key/value tuples.
///
/// - Returns: A tuple with two arrays, an `Array` of keys and an `Array` of values.
func unzip<K, V>() -> ([K], [V]) where Element == (key: K, value: V) {
var keys = [K]()
var values = [V]()
keys.reserveCapacity(count)
values.reserveCapacity(count)
forEach { key, value in
keys.append(key)
values.append(value)
}
return (keys, values)
}
}
随心所欲地实现它,但是当您将它放在函数中时,您可以更加清晰和明确。
关于arrays - 与 Swift `zip` 相反——将元组拆分为两个数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46043902/