如何在 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]) -&gt; T? throws) rethrows -&gt; [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。使用ArrayflatMap(_:) 方法展平数组

对于 Swift,符合Sequence 协议的类型(包括Array)有一个flatMap(_:) 方法。 ArrayflatMap(_:) 有以下声明:

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。使用Arrayjoined() 方法展平数组

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。使用 Arrayreduce(_:_:) 方法展平数组

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 中快速展平数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何在一维数组中“展平”或“索引”3维数组?

如何在 PHP 中展平数组?

如何在熊猫数据框中展平数组

如何使用 pyspark 在 aws 胶水中展平嵌套 json 中的数组?

如何在 Azure 数据工厂中正确展平分号数组?

如何在不使用 NumPy 复制的情况下展平多维数组的轴?