与 Swift `zip` 相反——将元组拆分为两个数组 [英] Opposite of Swift `zip` — split tuple into two arrays
问题描述
我有一个键值对数组:
let arr = [(key:"hey", value:["ho"]), (key:"ha", value:["tee", "hee"])]
我将其拆分为两个数组,如下所示:
I'm splitting it into two arrays, like this:
let (keys, values) = (arr.map{$0.key}, arr.map{$0.value})
实际上,这与 zip
相反——我将一个元组数组变成两个数组.
Effectively, that's the opposite of zip
— I'm turning an array of tuples into two arrays.
但我不喜欢我两次调用 map
的事实,因为这意味着我要遍历数组两次.然而,我也不想事先将两个目标数组声明为空数组并在附加时循环一次,例如与 forEach
.是否有一些很棒的 Swifty 习惯用法可以将我的元组数组解压缩为两个数组?
But I don't like the fact that I'm calling map
twice, because that means I'm looping through the array twice. Yet neither do I want to declare the two target arrays beforehand as empty arrays and loop once while appending, e.g. with forEach
. Is there some wonderful Swifty idiom for unzipping my array of tuples into two arrays?
推荐答案
在 Swift 4 中,你可以使用 reduce(into:)
:
In Swift 4, you can use reduce(into:)
:
let (keys, values) = arr.reduce(into: ([String](), [[String]]())) {
$0.0.append($1.key)
$0.1.append($1.value)
}
你说:
但我也不想事先将两个目标数组声明为空数组并在附加时循环一次,例如使用 forEach
.
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
方法的低效率.
Personally, that's precisely what I would do. I would just write a function that does this (that way you're not sprinkling your code with that pattern). But I think the following is much more clear and intuitive than the reduce
pattern, but doesn't suffer the inefficiency of the dual-map
approach.
/// 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)
}
或者,如果您觉得有必要将其设为扩展
,您也可以这样做:
Or, if you feel compelled to make it an extension
, you can do that, too:
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)
}
}
随心所欲地实现它,但是当你在一个函数中使用它时,你可以支持清晰和意图.
Implement this however you'd like, but when you have it in a function, you can favor clarity and intent.
这篇关于与 Swift `zip` 相反——将元组拆分为两个数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!