扁平化数组的数组在Swift

在Swift中有没有对应的flatten在Scala, Xtend, Groovy, Ruby和co?

var aofa = [[1,2,3],[4],[5,6,7,8,9]]
aofa.flatten() // shall deliver [1,2,3,4,5,6,7,8,9]

当然我可以用reduce来做,但那有点糟糕

var flattened = aofa.reduce(Int[]()){
a,i in var b : Int[] = a
b.extend(i)
return b
}
101649 次浏览

Swift >= 3.0

reduce:

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let reduced = numbers.reduce([], +)

flatMap:

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let flattened = numbers.flatMap { $0 }

joined:

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let joined = Array(numbers.joined())

enter image description here

reduce的另一个更通用的实现,

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let reduced = reduce(numbers,[],+)

这完成了同样的事情,但可能会让你更深入地了解reduce中发生了什么。

从苹果公司的文件来看,

func reduce<S : SequenceType, U>(sequence: S, initial: U, combine: (U, S.Generator.Element) -> U) -> U

描述

返回反复调用结合的结果,其中累积值初始化为最初的序列的每个元素。

使用joined()代替:

https://developer.apple.com/documentation/swift/sequence/2431985-joined

最初的回答:

let numbers = [[1, 2, 3], [4, 5, 6]]
let flattenNumbers = numbers.reduce([], combine: +)

在Swift标准库中,为所有符合Sequence协议的类型实现了joined函数(或在Swift 3之前的SequenceType上的flatten),其中包括Array:

let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let flattened = Array(numbers.joined())

在某些情况下,使用joined()可能是有益的,因为它返回一个惰性集合而不是一个新数组,但当传递给Array()初始化器时,总是可以转换为一个数组,就像上面的例子一样。

func convert(){
let arr = [[1,2,3],[4],[5,6,7,8,9]]
print("Old Arr = ",arr)
var newArr = [Int]()
for i in arr{
for j in i{
newArr.append(j)
}
}
print("New Arr = ",newArr)
}

enter image description here

迅速的4.倍和5.倍

为了在数组中增加一点复杂性,如果有一个数组包含数组的数组,那么flatMap实际上会失败。

假设数组是

var array:[Any] = [1,2,[[3,4],[5,6,[7]]],8]

flatMapcompactMap返回的是:

array.compactMap({$0})


//Output
[1, 2, [[3, 4], [5, 6, [7]]], 8]

为了解决这个问题,我们可以使用简单的for循环逻辑+递归

func flattenedArray(array:[Any]) -> [Int] {
var myArray = [Int]()
for element in array {
if let element = element as? Int {
myArray.append(element)
}
if let element = element as? [Any] {
let result = flattenedArray(array: element)
for i in result {
myArray.append(i)
}


}
}
return myArray
}

用给定的数组调用这个函数

flattenedArray(array: array)

结果是:

[1, 2, 3, 4, 5, 6, 7, 8]

考虑到这里的Int的情况,这个函数将帮助平摊任何类型的数组

< >强操场输出: enter image description here < / p >

快4.倍

flatMap的这种用法并没有被弃用,它就是为此而生的。 https://developer.apple.com/documentation/swift/sequence/2905332-flatmap < / p >
var aofa = [[1,2,3],[4],[5,6,7,8,9]]
aofa.flatMap { $0 } //[1,2,3,4,5,6,7,8,9]

你可以用下面的方法来平嵌套数组:

var arrays = [1, 2, 3, 4, 5, [12, 22, 32], [[1, 2, 3], 1, 3, 4, [[[777, 888, 8999]]]]] as [Any]


func flatten(_ array: [Any]) -> [Any] {


return array.reduce([Any]()) { result, current in
switch current {
case(let arrayOfAny as [Any]):
return result + flatten(arrayOfAny)
default:
return result + [current]
}
}
}


let result = flatten(arrays)


print(result)


/// [1, 2, 3, 4, 5, 12, 22, 32, 1, 2, 3, 1, 3, 4, 777, 888, 8999]

斯威夫特4.2

我在下面写了一个简单的数组扩展。可用于将包含另一个数组或元素的数组平展。不像joined()方法。

public extension Array {
public func flatten() -> [Element] {
return Array.flatten(0, self)
}


public static func flatten<Element>(_ index: Int, _ toFlat: [Element]) -> [Element] {
guard index < toFlat.count else { return [] }


var flatten: [Element] = []


if let itemArr = toFlat[index] as? [Element] {
flatten = flatten + itemArr.flatten()
} else {
flatten.append(toFlat[index])
}


return flatten + Array.flatten(index + 1, toFlat)
}
}

用法:

let numbers: [Any] = [1, [2, "3"], 4, ["5", 6, 7], "8", [9, 10]]


numbers.flatten()

修改@RahmiBozdag的回答, 1. 公共扩展中的方法是公共的。 2. 删除了额外的方法,因为开始索引将始终为零。 3.我没有找到一种方法把compactMap内部为nil和可选的,因为内部方法T总是[Any?

.
 let array = [[[1, 2, 3], 4], 5, [6, [9], 10], 11, nil] as [Any?]


public extension Array {


func flatten<T>(_ index: Int = 0) -> [T] {
guard index < self.count else {
return []
}


var flatten: [T] = []


if let itemArr = self[index] as? [T] {
flatten += itemArr.flatten()
} else if let element = self[index] as? T {
flatten.append(element)
}
return flatten + self.flatten(index + 1)
}


}


let result: [Any] = array.flatten().compactMap { $0 }
print(result)
//[1, 2, 3, 4, 5, 6, 9, 10, 11]
Apple Swift version 5.1.2 (swiflang -1100.0.278 clang-1100.0.33.9)
目标:x86_64-apple-darwin19.2.0 < / p >

截图

let optionalNumbers = [[1, 2, 3, nil], nil, [4], [5, 6, 7, 8, 9]]
print(optionalNumbers.compactMap { $0 }) // [[Optional(1), Optional(2), Optional(3), nil], [Optional(4)], [Optional(5), Optional(6), Optional(7), Optional(8), Optional(9)]]
print(optionalNumbers.compactMap { $0 }.reduce([], +).map { $0 as? Int ?? nil }.compactMap{ $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(optionalNumbers.compactMap { $0 }.flatMap { $0 }.map { $0 as? Int ?? nil }.compactMap{ $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(Array(optionalNumbers.compactMap { $0 }.joined()).map { $0 as? Int ?? nil }.compactMap{ $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]


let nonOptionalNumbers = [[1, 2, 3], [4], [5, 6, 7, 8, 9]]
print(nonOptionalNumbers.compactMap { $0 }) // [[1, 2, 3], [4], [5, 6, 7, 8, 9]]
print(nonOptionalNumbers.reduce([], +)) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(nonOptionalNumbers.flatMap { $0 }) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(Array(nonOptionalNumbers.joined())) // [1, 2, 3, 4, 5, 6, 7, 8, 9]

矩阵是[[myDTO]]?

在swift 5中,你可以使用this = Array(self.matrix!.joined())

斯威夫特5.1

public extension Array where Element: Collection {


func flatten() -> [Element.Element] {
return reduce([], +)
}
}

如果你也想在Dictionary值中使用它:

public extension Dictionary.Values where Value : Collection {
func flatten() -> [Value.Element]{
return self.reduce([], +)
}
}