#21 Rubyで学ぶコレクション操作の応用(フィルタ・マップ的な考え方)の基本
Rubyの「コレクション操作」って何?
Rubyでプログラムを書いていると、配列(複数の値をまとめて入れておく入れ物)やハッシュ(キーと値のペアを保存する入れ物)を何度も操作することになります。こうした「複数のデータをまとめて扱うもの」のことを、まとめてコレクションと呼びます。
こうした操作を「for文で1件ずつ処理する」代わりに、RubyではEnumerableという仕組み(モジュール、いわば「メソッドの詰め合わせセット」)を使います。これにより、短く読みやすく書けます。この記事では初心者がつまずきやすい点を中心に紹介します。
条件で絞り込む: select / reject
配列から条件に合う要素だけを取り出したいときはselect(またはfilter、同じ意味です)を使います。逆に「条件に合わないものだけ」を残したいときはrejectを使います。
numbers = [1, 2, 3, 4, 5, 6]
evens = numbers.select { |n| n.even? }
# => [2, 4, 6]
odds = numbers.reject { |n| n.even? }
# => [1, 3, 5]
{ |n| ... }の部分はブロックと呼ばれ、「各要素に対して行う処理」を書く場所です。nには配列の要素が1つずつ入り、その結果がtrueかfalseかで残すかどうかが決まります。他の言語のif文のように書けるので、慣れると直感的です。
値を加工する: map / collect
すべての要素に同じ処理を適用して新しい配列を作りたいときはmap(collectでも同じ)を使います。
prices = [100, 200, 300]
with_tax = prices.map { |p| (p * 1.1).round }
# => [110, 220, 330]
ここで注意したいのが、mapとeachの違いです。eachは「1件ずつ処理を実行するだけ」で戻り値は元の配列のままですが、mapは「ブロックの戻り値を集めた新しい配列」を返します。初心者がよく混同するポイントなので、「加工した結果の配列がほしいならmap、単に処理をしたいだけならeach」と覚えておくと安心です。
集計する: reduce / sum
要素をまとめて1つの値にしたい場合はreduce(injectとも呼ばれます)やsumを使います。
total = [1, 2, 3, 4].reduce(0) { |acc, n| acc + n }
# => 10
total2 = [1, 2, 3, 4].sum
# => 10
単純な合計ならsumだけで十分ですが、reduceは「累積した値(上の例ではacc)」と「今の要素(n)」を使って自由な集計ができます。そのため、合計以外の複雑な処理(文字列の連結、最大値の計算など)にも応用できます。
メソッドチェーンで組み合わせる
Rubyの強みは、これらのメソッドを「.(ドット)」でつなげて連続実行できる点です。
result = (1..10).select { |n| n.even? }
.map { |n| n * n }
.sum
# => 220
「偶数だけ選ぶ → 2乗する → 合計する」という処理が、for文を使わずに1つの流れとして読めます。慣れないうちは1行ずつ変数に代入して確認しながら書くのがおすすめです。途中経過を追いやすくなります。
他言語との違い
Pythonでは[x*x for x in nums if x % 2 == 0]のようなリスト内包表記で同じことができます。JavaScriptではnums.filter(...).map(...)のように書きます。Rubyは配列だけでなくハッシュや範囲(Range)にも同じメソッドが使えるのが特徴で、書き方に一貫性があります。
つまずきやすいポイント
- 破壊的メソッドとの混同:
select!やmap!のように末尾に!が付くメソッドは、元の配列そのものを書き換えます(破壊的メソッドと呼ばれます)。うっかり元データを失わないよう、まずは!なしのメソッドで試すのが安全です。 - ハッシュへのmap:
mapをハッシュに使うとキーと値のペアが渡されます。hash.map { |key, value| ... }のように受け取ると分かりやすいです。 - 大量データでの遅延評価: 巨大な配列や無限のRangeを扱う場合、
.lazyを使うと必要な分だけ計算するようになり、無駄な処理を減らせます(発展的な内容なので、慣れてきたら調べてみてください)。
まとめ
Rubyのコレクション操作は、selectで絞り込み、mapで加工し、reduceやsumで集計する、という3つの基本を押さえることが大切です。この3つを意識するだけで、for文よりもずっと読みやすいコードが書けるようになります。最初はメソッド名の使い分けに戸惑うかもしれませんが、「配列がほしいならmap、条件で選ぶならselect」と意識しながら書いていけば、自然と手が動くようになります。ぜひ普段のfor文を、少しずつこれらのメソッドに置き換えて練習してみてください。
関連記事
本ページはプロモーションを含みます。
参考書籍(PR)
Rubyをもっと学びたい方には「プロを目指す人のためのRuby入門[改訂2版]」がおすすめです。
PR
コードを書かずに自動化したい方へ
「学んだけど自分の作業に組み込む時間がない」という方向けに、ダブルクリックで動くWindows専用の自動化ツールをオーダーメイドで作成しています。気になる方はこちらをご覧ください。
コメント
コメントを投稿