MENU

【Swift入門】compactMapとは?使い方を初心者向けにわかりやすく解説

Swiftでコレクション(配列など)を扱う際、データの変換とフィルタリングを同時に行いたい場面は多くあります。そんなときに便利なのがcompactMapというメソッドです。

この記事では、Swift初心者の方に向けて、compactMapの基本から実践的な使い方まで、わかりやすく解説します。

目次

compactMapとは?

compactMapは、Swiftの配列やその他のコレクション型で使用できるメソッドで、次の2つの処理を同時に行います。

  1. 各要素を変換する(マッピング)
  2. 結果がnilの要素を自動的に除外する(フィルタリング)

簡単に言えば、「変換してnilを取り除く」メソッドです。

compactMapの基本的な使い方

文字列を数値に変換する例

最もわかりやすい例として、文字列の配列を数値の配列に変換してみましょう。

let stringNumbers = ["1", "2", "three", "4", "five"]
let numbers = stringNumbers.compactMap { Int($0) }
print(numbers)
// 出力: [1, 2, 4]

何が起きているのか?

  1. “1” → Int("1") → 1に変換成功
  2. “2” → Int("2") → 2に変換成功
  3. “three” → Int("three") → 変換失敗でnil
  4. “4” → Int("4") → 4に変換成功
  5. “five” → Int("five") → 変換失敗でnil

compactMapは変換に失敗してnilになった要素を自動的に除外してくれるため、結果は[1, 2, 4]となります。

mapとの違いを理解する

compactMapを理解するには、通常のmapとの違いを知ることが重要です。

mapを使った場合

let stringNumbers = ["1", "2", "three", "4"]
let result = stringNumbers.map { Int($0) }
print(result)
// 出力: [Optional(1), Optional(2), nil, Optional(4)]

mapは全ての要素を変換しますが、nilもそのまま残ります。結果は[Int?]型(オプショナルの配列)になります。

compactMapを使った場合

let stringNumbers = ["1", "2", "three", "4"]
let result = stringNumbers.compactMap { Int($0) }
print(result)
// 出力: [1, 2, 4]

compactMapはnilを自動的に除外し、結果は[Int]型(非オプショナルの配列)になります。

比較表

メソッドnil要素の扱い結果の型用途
mapnilも含まれる[Int?]全要素を変換したい
compactMapnilは除外される[Int]nilを除外して変換したい

compactMapの実践的な使い方

1. オプショナル配列から値を取り出す

let optionalNumbers: [Int?] = [1, nil, 3, nil, 5, 6]
let validNumbers = optionalNumbers.compactMap { $0 }
print(validNumbers)
// 出力: [1, 3, 5, 6]

これは最もシンプルな使い方で、オプショナル配列から非nilの値だけを取り出します。

2. 型変換とフィルタリングを同時に行う

let mixedData = ["apple", "100", "banana", "200", "cherry", "300"]
let prices = mixedData.compactMap { Int($0) }
print(prices)
// 出力: [100, 200, 300]

文字列と数値が混在したデータから、数値だけを抽出できます。

3. URLの配列を作成する

let urlStrings = [
    "https://example.com",
    "not a url",
    "https://apple.com",
    "invalid url format"
]

let validURLs = urlStrings.compactMap { URL(string: $0) }
print(validURLs.count)
// 出力: 2(有効なURLは2つ)

無効なURL文字列を自動的に除外して、有効なURL配列を作成できます。

4. ネストした配列の処理

let nestedArrays: [[Int]?] = [[1, 2], nil, [3, 4], nil, [5]]
let flattenedArrays = nestedArrays.compactMap { $0 }
print(flattenedArrays)
// 出力: [[1, 2], [3, 4], [5]]

5. カスタム変換ロジック

struct User {
    let name: String
    let age: Int
}

let userData = [
    ["name": "太郎", "age": "25"],
    ["name": "花子", "age": "invalid"],
    ["name": "次郎", "age": "30"]
]

let users = userData.compactMap { dict -> User? in
    guard let name = dict["name"],
          let ageString = dict["age"],
          let age = Int(ageString) else {
        return nil
    }
    return User(name: name, age: age)
}

print(users.count)
// 出力: 2(有効なユーザーは2人)

辞書データから構造体を作成する際、無効なデータを自動的にスキップできます。

compactMapを使うべき場面

compactMapは以下のような場面で特に有効です。

  1. 型変換が失敗する可能性がある場合
    • 文字列から数値への変換
    • 文字列からURLやDateへの変換
  2. オプショナル配列から非nilの値だけが欲しい場合
    • データベースやAPIから取得したオプショナルデータの処理
  3. 無効なデータをスキップしたい場合
    • ユーザー入力の検証とフィルタリング
    • ファイルパースでの不正データの除外

よくある間違いと注意点

1. flatMapとの混同

Swift 4.1以前では、compactMapの機能はflatMapという名前でした。現在のSwiftでは、flatMapは別の用途(ネストした配列の平坦化)に使われるため、混同しないよう注意しましょう。

// 古いコード(非推奨)
let result = array.flatMap { Int($0) }

// 新しいコード
let result = array.compactMap { Int($0) }

2. パフォーマンスの考慮

compactMapは便利ですが、大量のデータを処理する場合はパフォーマンスに注意が必要です。必要に応じて、filtermapを分けて使うことも検討しましょう。

// compactMapを使う場合
let result1 = array.compactMap { transform($0) }

// filterとmapを分ける場合
let result2 = array.filter { isValid($0) }.map { transform($0) }

まとめ

compactMapは、Swiftでデータ処理を行う際に非常に便利なメソッドです。

ポイントのおさらい:

  • compactMapは「変換」と「nilの除外」を同時に行う
  • mapとの違いは、nilを自動的に除外すること
  • 型変換が失敗する可能性がある場合に特に有効
  • オプショナル配列から非nilの値を取り出すのに便利

初心者の方は、まずシンプルな例から試してみて、徐々に複雑なケースにも挑戦してみてください。compactMapをマスターすれば、よりシンプルで読みやすいSwiftコードが書けるようになります。

参考リンク

プログラミングの独学におすすめ
プログラミング言語の人気オンラインコース
独学でプログラミングを学習している方で、エラーなどが発生して効率よく勉強ができないと悩む方は多いはず。Udemyは、プロの講師が動画で実際のプログラムを動かしながら教えてくれるオンライン講座です。講座の価格は、セール期間中には専門書籍を1冊買うよりも安く済むことが多いです。新しく学びたいプログラミング言語がある方は、ぜひUdemyでオンライン講座を探してみてください。
目次