#21 Swiftで学ぶコレクション操作の応用(フィルタ・マップ的な考え方)の基本
はじめに
Swiftで配列(複数の値をまとめて扱う入れ物、Array)を使っていると、いくつかの処理をしたくなる場面によく出会います。たとえば「条件に合う要素だけ取り出したい」「全要素を別の形に変換したい」「全要素を集計して1つの値にしたい」といった場面です。こうした処理はfor文でも書けますが、Swiftにはfilter・map・reduceという専用のメソッド(コレクション操作の応用)が用意されています。これらを使うと、目的が一目で分かる短いコードになります。この記事では、この3つの基本的な使い方と、初心者がつまずきやすいポイントを解説します。
filter:条件に合う要素だけを絞り込む
filterは、配列の中から「条件を満たす要素だけ」を新しい配列として取り出すメソッドです。条件を判定する処理(クロージャと呼ばれる、その場で書ける小さな関数のようなもの)を引数として渡します。
let numbers = [1, 2, 3, 4, 5, 6]
let evens = numbers.filter { $0 % 2 == 0 }
// evens は [2, 4, 6]
$0は「クロージャに渡された1つ目の引数」を指す省略記法で、ここでは配列の各要素を表します。{ $0 % 2 == 0 }は「2で割った余りが0(=偶数)」という条件です。filterは条件がtrueだった要素だけを集めて新しい配列を返すので、元のnumbersは変更されません。この「元の配列を壊さず、新しい配列を作る」性質は、Swiftのコレクション操作全体に共通する特徴です。意図せず元データを書き換えてしまうバグを防いでくれます。
map:全要素を別の形に変換する
mapは、配列の全要素に同じ処理を適用し、変換後の値を新しい配列として返します。
let names = ["taro", "hanako", "jiro"]
let upperNames = names.map { $0.uppercased() }
// upperNames は ["TARO", "HANAKO", "JIRO"]
ここではuppercased()(文字列を大文字に変換するメソッド)を各要素に適用しています。mapは要素数を変えずに中身だけ変換したいときに使う、という点がfilterとの違いです。
reduce:全要素を1つの値にまとめる
reduceは、配列の全要素を順番に処理しながら1つの値に集約(合計・連結など)するメソッドです。初期値と、要素を1つずつ足し込んでいく処理を指定します。
let numbers = [1, 2, 3, 4, 5]
let total = numbers.reduce(0) { $0 + $1 }
// total は 15
最初の引数0が初期値で、クロージャの$0がここまでの計算結果、$1が今処理している要素です。合計を求める場合はさらに省略してnumbers.reduce(0, +)と書くこともできます。慣れないうちは省略せずに{ $0 + $1 }の形で書き、動きが理解できてから短く書き直すのがおすすめです。
3つを組み合わせる
これらは連続して呼び出す(メソッドチェーンと呼びます)ことができます。
let scores = [55, 80, 42, 90, 65]
let passedTotal = scores
.filter { $0 >= 60 }
.map { $0 * 1.1 }
.reduce(0, +)
「60点以上を絞り込み→1.1倍のボーナス点に変換→合計する」という処理が、for文を使わずに1行の流れとして書けます。処理の意図がコードの見た目からそのまま読み取れるのが大きな利点です。ただし、チェーンが長くなりすぎると1行で何をしているか逆に読みにくくなるため、複雑な処理は途中で変数に分けて分割するとよいでしょう。
他言語との違い・つまずきやすい点
PythonやJavaScriptにも同様の機能(内包表記やArray.prototype.mapなど)がありますが、Swiftのfilter・map・reduceは型(値の種類)に厳密です。mapで数値配列を文字列配列に変換すると、戻り値の型も自動的に[String]になります。慣れないうちは、変換後の型が何になっているかXcode(Swiftの開発ツール)の型推論の補完で確認しながら書くと安心です。また、空の配列にreduceを使っても、初期値がそのまま返るだけでエラーにはなりません。ただしfirstや強制アンラップを使う処理では、空配列がクラッシュの原因になりやすいため注意しましょう。
まとめ
filterは絞り込み、mapは変換、reduceは集約、とそれぞれ役割がはっきりしています。最初はfor文で書いてから「これはfilterで書けないか」と置き換えてみると、自然に使い分けが身についていきます。短く書けることよりも、まずは「何をしたいコードなのか」が読み手に伝わることを意識して使ってみてください。
関連記事
本ページはプロモーションを含みます。
参考書籍(PR)
Swiftをもっと学びたい方には「これからつくる iPhoneアプリ開発入門」がおすすめです。
PR
コードを書かずに自動化したい方へ
「学んだけど自分の作業に組み込む時間がない」という方向けに、ダブルクリックで動く Windows専用の自動化ツールをオーダーメイドで作成しています。気になる方は こちらをご覧ください。
コメント
コメントを投稿