Swift Language Flattening the result of an Array transformation with flatMap(_:)


As well as being able to create an array by filtering out nil from the transformed elements of a sequence, there is also a version of flatMap(_:) that expects the transformation closure to return a sequence S.

extension SequenceType {
    public func flatMap<S : SequenceType>(transform: (Self.Generator.Element) throws -> S) rethrows -> [S.Generator.Element]

Each sequence from the transformation will be concatenated, resulting in an array containing the combined elements of each sequence – [S.Generator.Element].

Combining the characters in an array of strings

For example, we can use it to take an array of prime strings and combine their characters into a single array:

let primes = ["2", "3", "5", "7", "11", "13", "17", "19"]
let allCharacters = primes.flatMap { $0.characters }
// => "["2", "3", "5", "7", "1", "1", "1", "3", "1", "7", "1", "9"]"

Breaking the above example down:

  1. primes is a [String] (As an array is a sequence, we can call flatMap(_:) on it).
  2. The transformation closure takes in one of the elements of primes, a String (Array<String>.Generator.Element).
  3. The closure then returns a sequence of type String.CharacterView.
  4. The result is then an array containing the combined elements of all the sequences from each of the transformation closure calls – [String.CharacterView.Generator.Element].

Flattening a multidimensional array

As flatMap(_:) will concatenate the sequences returned from the transformation closure calls, it can be used to flatten a multidimensional array – such as a 2D array into a 1D array, a 3D array into a 2D array etc.

This can simply be done by returning the given element $0 (a nested array) in the closure:

// A 2D array of type [[Int]]
let array2D = [[1, 3], [4], [6, 8, 10], [11]]

// A 1D array of type [Int]
let flattenedArray = array2D.flatMap { $0 }

print(flattenedArray) // [1, 3, 4, 6, 8, 10, 11]