Rubyの配列の便利メソッドとは?map・select・reduceの使い方を解説

PR Ruby

Rubyの配列の便利メソッドとは?map・select・reduceの使い方を解説

💡 この記事でわかること

  • each だけでなく、配列に用意されている便利なメソッド(Enumerable)の存在
  • map:各要素を変換した新しい配列を作る方法
  • selectrejectfind:条件で絞り込む・探す方法
  • reduce(inject)で合計などを集計する方法、each_with_object との違い
  • sortuniqsum など、覚えておくと便利なメソッド一覧

1. 配列の便利メソッドとは?

配列の繰り返しというと、
👉 each で1つずつ処理する方法をすでに紹介しました。ですが実際のコードでは、each だけでなく「変換する」「絞り込む」「集計する」といった専用のメソッドがよく使われます。

これらのメソッドは Enumerable というしくみによって、配列(Array)やハッシュ(Hash)などに共通して用意されています。1つずつfor文で書くよりも、目的に合ったメソッドを使うほうが短く・読みやすいコードになります。

👉 配列の作り方・基本操作についての記事はこちら


2. map ― 要素を変換した新しい配列を作る

map は、配列の各要素にブロックの処理を適用し、その結果を集めた新しい配列を返すメソッドです。

nums = [1, 2, 3, 4]

doubled = nums.map { |n| n * 2 }
p doubled   # [2, 4, 6, 8]
p nums      # [1, 2, 3, 4](元の配列は変わらない)

👉 each は「処理をするだけ」で戻り値は元の配列のままですが、map は「変換した結果の配列」を返します。「新しい配列がほしいとき」は map、「表示するだけなど処理だけしたいとき」は each、と使い分けます。

💡 末尾に ! を付けた map! は、新しい配列を作らず元の配列そのものを書き換えます。破壊的メソッドと呼ばれ、意図せず元のデータを変えてしまう原因になりやすいので、まずは ! なしの map に慣れるのがおすすめです。


3. select・reject・find ― 条件で絞り込む・探す

select はブロックの条件が true になる要素だけを集めた配列を返します。reject はその逆で、条件が false の要素だけを集めます。

nums = [1, 2, 3, 4, 5, 6]

evens = nums.select { |n| n.even? }
p evens   # [2, 4, 6]

odds = nums.reject { |n| n.even? }
p odds    # [1, 3, 5]

「条件に合う最初の1つだけ」がほしいときは find(別名 detect)を使います。見つからなければ nil が返ります。

nums = [1, 2, 3, 4, 5, 6]

first_even = nums.find { |n| n.even? }
p first_even   # 2

4. reduce(inject) ― 集計する

reduce(別名 inject)は、配列の要素を1つにまとめて集計するメソッドです。合計・最大値など「畳み込み」の処理に使います。

nums = [1, 2, 3, 4]

total = nums.reduce(0) { |sum, n| sum + n }
p total   # 10

# 初期値を省略すると、最初の要素が初期値になる
total2 = nums.reduce { |sum, n| sum + n }
p total2  # 10

# 記号だけでも書ける(よく見る書き方)
total3 = nums.reduce(:+)
p total3  # 10

reduce のブロックには「それまでの集計結果(sum)」と「今見ている要素(n)」が渡され、ブロックの戻り値が次の回の sum になります

💡 ブロックの最後に sum + n のような「次に渡す値」を書き忘れると、集計結果がおかしくなります(たとえば途中で puts だけ書いて終えると、sumnil になってしまいます)。reduce は「ブロックの戻り値がそのまま次の引数になる」という点を意識して使いましょう。

👉 戻り値の考え方(メソッドの最後に評価した式が返る)についての記事はこちら


5. each_with_object ― 集計用オブジェクトを組み立てる

reduce は数値の合計のような「1つの値」を作るのは得意ですが、配列やハッシュを組み立てていく場合は each_with_object のほうが書きやすいことがあります。ブロックの戻り値を意識しなくてよいのが特徴です。

words = ["apple", "banana", "fig"]

# 単語ごとの文字数を、ハッシュに集めていく
lengths = words.each_with_object({}) do |word, hash|
  hash[word] = word.length
end

p lengths   # {"apple"=>5, "banana"=>6, "fig"=>3}

👉 each_with_object(初期値) に渡した初期値(ここでは {})がブロックに渡され、それを毎回書き換えていくだけでよく、最後に each_with_object 自身がその初期値を返してくれますreduce のように「次に渡す値を毎回returnする」必要がないぶん、配列やハッシュを組み立てるときはこちらのほうが直感的です。


6. sort・sort_by ― 並べ替える

sort は要素を並べ替えた新しい配列を返します。数値や文字列はそのまま昇順に並びます。

nums = [3, 1, 4, 1, 5]
p nums.sort           # [1, 1, 3, 4, 5]
p nums.sort { |a, b| b <=> a }   # [5, 4, 3, 1, 1](降順)

ハッシュの配列など「何を基準に並べるか」を指定したいときは sort_by が便利です。ブロックで「並び替えの基準にする値」を返すだけで、比較のしかたを自分で書く必要がありません。

users = [
  { name: "太郎", age: 25 },
  { name: "花子", age: 20 },
  { name: "次郎", age: 30 }
]

by_age = users.sort_by { |user| user[:age] }
p by_age.map { |user| user[:name] }   # ["花子", "太郎", "次郎"]

👉 sort { |a, b| ... } は2つの要素を比較する式(<=>)を自分で書く必要がありますが、sort_by { |x| ... } は「基準になる値」を返すだけで済みます。降順にしたい場合は sort_by { |user| -user[:age] } のようにマイナスを付けるのが定番です。


7. その他よく使うメソッド

ここまでのほかにも、覚えておくと便利なメソッドがあります。

nums = [3, 1, 2, 2, 3]

p nums.uniq     # [3, 1, 2](重複を取り除く)
p nums.sum      # 11(合計)
p nums.min      # 1
p nums.max      # 3
p nums.count { |n| n.odd? }   # 3(条件に合う個数)

nested = [[1, 2], [3, 4]]
p nested.flatten   # [1, 2, 3, 4](配列の入れ子を平らにする)

👉 「配列に対してやりたいこと」から逆引きでメソッド名を覚えていくのがおすすめです。すべてを暗記する必要はなく、「変換なら map、絞り込みなら select」という大まかな対応が頭に入っていれば、あとは調べながら書けます。


8. メソッドチェーンで組み合わせる

これらのメソッドは、. でつなげて組み合わせる(メソッドチェーン)ことができます。「絞り込んでから変換する」といった処理も1行で書けます。

nums = [1, 2, 3, 4, 5, 6]

# 偶数だけを2倍にした配列
result = nums.select { |n| n.even? }.map { |n| n * 2 }
p result   # [4, 8, 12]

👉 1つ前のメソッドが返した配列に対して、次のメソッドが実行されます。長くつなげすぎると読みにくくなるので、最初は2〜3個までを目安に組み合わせるとよいでしょう。


9. 配列メソッド 早見表

メソッドやること
each1つずつ処理する(戻り値は元の配列)
map各要素を変換した新しい配列を作る
select / reject条件に合う / 合わない要素を集める
find条件に合う最初の1つを探す(なければ nil)
reduce(inject)集計して1つの値にまとめる
each_with_object配列・ハッシュを組み立てながら集計する
sort / sort_by並べ替える
uniq / flatten重複を除く / 入れ子を平らにする
sum / min / max / count合計・最小・最大・件数を求める

10. まとめ

  • 配列には each のほかに、変換・絞り込み・集計のための便利なメソッド(Enumerable)が用意されている
  • map は変換、selectrejectfind は絞り込み・検索に使う
  • reduce は集計に便利だが、ブロックの戻り値が次の値になる点に注意。組み立てなら each_with_object も選択肢
  • 並べ替えは sort / sort_by、そのほか uniqsum なども覚えておくと便利
  • メソッドは . でつなげて組み合わせられる(メソッドチェーン)

👉 最初から全部を覚えようとせず、まずは mapselect の2つから使ってみましょう。この2つだけでも、for文を書くよりずっとすっきりしたコードになります。慣れてきたら reducesort_by を試してみてください。

-Ruby
-, , ,