Flatten an Array of Arrays in Swift
In Swift standard library there is joined
function implemented for all types conforming to Sequence
protocol (or flatten
on SequenceType
before Swift 3), which includes Array
:
let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let flattened = Array(numbers.joined())
In certain cases use of joined()
can be beneficial as it returns a lazy collection instead of a new array, but can always be converted to an array when passed to Array()
initialiser like in the example above.
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())
Swift 4.x
This usage of flatMap
isn't deprecated and it's make for this.
https://developer.apple.com/documentation/swift/sequence/2905332-flatmap
var aofa = [[1,2,3],[4],[5,6,7,8,9]]
aofa.flatMap { $0 } //[1,2,3,4,5,6,7,8,9]
Swift 4.x/5.x
Just to add a bit more complexity in the array, if there is an array that contains array of arrays, then flatMap
will actually fail.
Suppose the array is
var array:[Any] = [1,2,[[3,4],[5,6,[7]]],8]
What flatMap
or compactMap
returns is:
array.compactMap({$0})
//Output
[1, 2, [[3, 4], [5, 6, [7]]], 8]
In order to solve this problem, we can use our simple for loop logic + recursion
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
}
So call this function with the given array
flattenedArray(array: array)
The Result is:
[1, 2, 3, 4, 5, 6, 7, 8]
This function will help to flatten any kind of array, considering the case of Int
here
Playground Output: