如何在 Swift 中快速展平数组?
Posted
技术标签:
【中文标题】如何在 Swift 中快速展平数组?【英文标题】:How can I flatten an array swiftily in Swift? 【发布时间】:2016-09-10 07:27:16 【问题描述】:我想转这个:
let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
进入这个:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
非常优雅。
最直接的方法当然是
var y = [Int]()
x.forEach y.appendContentsOf($0)
但这会使结果数组可变,这是不必要的。我不喜欢这种方式。
我尝试使用reduce
:
let y = x.reduce([Int]()) (array, ints) -> [Int] in
array.appendContentsOf(ints)
return array
但是编译器抱怨array
是不可变的,所以我不能调用变异方法appendContentsOf
。
因此,我添加了一些东西:
let y = x.reduce([Int]()) (array, ints) -> [Int] in
var newArr = array
newArr.appendContentsOf(ints)
return newArr
这只是很糟糕。我有一种直觉,这并不快。
如何比上述方法更快地展平数组?单线就好了。
【问题讨论】:
Flatten a Array of Arrays in Swift的可能重复 【参考方案1】:为此有一个名为joined
的内置函数:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]].joined()
(请注意,这实际上并没有返回另一个数组,它返回一个FlattenSequence
,但这通常并不重要,因为它仍然是一个序列,你可以使用for
循环等等。如果你真的在乎,你可以使用Array(arrayOfArrays.joined())
。)
flatMap
function 也可以帮助您。它的签名大致是,
flatMap<S: SequenceType>(fn: (Generator.Element) -> S) -> [S.Generator.Element]
这意味着您可以传递一个fn
,它对于任何元素都会返回一个序列,并且它将组合/连接这些序列。
由于您的数组元素本身就是序列,您可以使用只返回元素本身的函数( x in return x
或等效地只是 $0
):
[[1, 2, 3], [4, 5, 6], [7, 8, 9]].flatMap $0
【讨论】:
哦,我明白了!我以前看过flatMap
。但我看错了——flatMap(transform: ([Int]) -> T? throws) rethrows -> [T]
。我想知道“这与map
有何不同?”现在我明白了。谢谢!
是的!有多种平面地图。去阅读有关 monad 的内容,您可能会明白为什么它们具有相同的名称 :-)
很高兴知道!我认为我们必须在循环之前转换类型,很高兴看到我们没有:)【参考方案2】:
数组中的扁平化函数:
let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let y = Array(x.flatten())
print(y)
数组中的flatMap函数:
let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let y = x.flatMap($0)
print(y)
你的输出:
更多:Array in Swift
【讨论】:
Swift中的Array结构没有flatten方法,而是joined方法。【参考方案3】:在 Swift 5 中,您可以选择以下三种方式之一来展平数组。
#1。使用Array
的flatMap(_:)
方法展平数组
对于 Swift,符合Sequence
协议的类型(包括Array
)有一个flatMap(_:)
方法。 Array
的flatMap(_:)
有以下声明:
func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence
返回一个数组,其中包含使用此序列的每个元素调用给定转换的连接结果。
下面的 Playground 示例代码显示了如何使用 flatMap(_:)
将类型为 [[Int]]
的 Array
展平为类型 [Int]
:
let array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let flattenArray = array.flatMap( (element: [Int]) -> [Int] in
return element
)
print(flattenArray) // prints [1, 2, 3, 4, 5, 6, 7, 8, 9]
#2。使用Array
的joined()
方法展平数组
Array
有一个名为joined()
的方法。 joined()
有以下声明:
func joined() -> FlattenSequence<Array<Element>>
返回此序列序列的元素,串联。
以下 Playground 示例代码展示了如何使用 joined()
将类型为 [[Int]]
的 Array
展平为类型 [Int]
:
let array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let flattenCollection = array.joined()
let flattenArray = Array(flattenCollection)
print(flattenArray) // prints [1, 2, 3, 4, 5, 6, 7, 8, 9]
#3。使用 Array
的 reduce(_:_:)
方法展平数组
Swift Array
有一个 reduce(_:_:)
方法,声明如下:
func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
返回使用给定闭包组合序列元素的结果。
以下 Playground 示例代码展示了如何使用 reduce(_:_:)
将类型为 [[Int]]
的 Array
展平为类型 [Int]
:
let array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let flattenArray = array.reduce([], (result: [Int], element: [Int]) -> [Int] in
return result + element
)
print(flattenArray) // prints [1, 2, 3, 4, 5, 6, 7, 8, 9]
作为reduce(_:_:)
的替代品,您可以使用reduce(into:_:)
:
let array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let flattenArray = array.reduce(into: [Int]()) (result: inout [Int], element: [Int]) in
result += element
print(flattenArray) // prints [1, 2, 3, 4, 5, 6, 7, 8, 9]
【讨论】:
【参考方案4】:你只需要使用 2 个函数来做到这一点
加入()
紧凑地图
让 y = x.compactMap$0.joined().compactMap$0
Reference for more about FlattenSequence
【讨论】:
以上是关于如何在 Swift 中快速展平数组?的主要内容,如果未能解决你的问题,请参考以下文章