iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

Swift で map, compactMap, flatMap を使いこなそう

今回は初学者向けに、Swift からプログラミング言語を学び始めた人が必ずいだく mapcompactMapflatMap の違いについて簡単に解説をしていきたいと思います。また、これらの関数は積極的に使っていくことで状況に応じた使い分けなどがうまくできるようになっていくので積極的に使っていきましょう!

map

map は主に配列のデータを別の配列データに変換したい時などに使用する関数です。たとえば、整数の配列を文字列の配列として変換する時のサンプルコードは下記のようになります。$0クロージャでの引数を参照することができます。クロージャーが分からない方はこちらの記事を見ていただければ把握できるかと思います。

let numberList: [Int] = [1, 2, 3, 4, 5, 6]

let numberStringList: [String] = numberList.map { "\($0)" }

print(numberStringList) // ["1", "2", "3", "4", "5", "6"]

compactMap

compactMap は配列のデータから nil を取り除きたい場合に使用する関数です。nil を含む配列から nil を取り除いた配列を取得するサンプルは次のようになります。

let optionalNumberList: [Int?] = [1, 2, nil, 4, 5, nil]

let numberList: [Int] = optionalNumberList.compactMap { $0 }

print(numberList) // [1, 2, 4, 5]

また、compactMap は配列で nil を取り除いてくれるので、配列のデータを使用して nil になる可能性のある別の型のデータ配列に変換する時などによく使用されます。また、偶数値を渡された時のみ初期化できる Event を整数値の配列から nil の値を取り出すして配列に変換するサンプルコードは下記になります。

struct Even {
    let evenString: String

    init?(number: Int) {
        if number % 2 == 0 {
            evenString = "\(number)"
        } else {
            return nil
        }
    }
}

let numberList: [Int] = [1, 2, 3, 4, 5, 6]

let eventList: [Even] = numberList.compactMap { Even(number: $0) }

print(eventList.map { $0.evenString }) // ["2", "4", "6"]

flatMap

flatMapクロージャー内で返された配列たちを(多次元配列)一次元配列に変換する際に利用します。サンプルコードとして、理解しやすいように map の結果と比較しています。

let numberList: [[Int]] = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]

let numberStringListWithFlatMap: [String] = numberList.flatMap { $0.map { "\($0)"} }
let numberStringListWithMap: [[String]] = numberList.map { $0.map { "\($0)" }}

print("flatMap: \(numberStringListWithFlatMap)") // flatMap: ["1", "2", "3", "1", "2", "3", "1", "2", "3"]
print("map: \(numberStringListWithMap)") // map: [["1", "2", "3"], ["1", "2", "3"], ["1", "2", "3"]]