Ruby 配列の変換・集計:map・inject・flat_map の使い方
配列を別の形に変換したり、合計・グループ化したりするには map・inject・flat_map を使います。
早わかりまとめ
| メソッド | 戻り値 | 向いている用途 |
|---|---|---|
map / collect |
配列 | 各要素を変換した新しい配列を作る |
inject / reduce |
任意の値 | 配列を1つの値に集計する |
flat_map |
配列 | 変換しながら1階層フラット化する |
flatten |
配列 | ネストした配列を平坦にする |
group_by |
ハッシュ | 条件でグループ化する |
tally |
ハッシュ | 要素の出現回数を数える |
sum |
数値 | 合計を計算する |
min / max |
要素 | 最小・最大を取り出す |
min_by / max_by |
要素 | 特定の値で最小・最大を取り出す |
map / collect:変換した新しい配列を作る
prices = [100, 200, 300] # 税込み価格の配列を作る with_tax = prices.map { |price| (price * 1.1).round } p with_tax # [110, 220, 330]
users = [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }]
# 名前だけの配列を作る
names = users.map { |user| user[:name] }
p names # ['Alice', 'Bob']
collect は map の別名です。
inject / reduce:集計する
inject は「配列を畳み込んで1つの値を作る」メソッドです。
numbers = [1, 2, 3, 4, 5] # 合計 sum = numbers.inject(0) { |acc, n| acc + n } p sum # 15 # inject(:+) と書ける省略形 p numbers.inject(:+) # 15 p numbers.inject(:*) # 120(積)
# 最大値 max = numbers.inject { |acc, n| acc > n ? acc : n } p max # 5
# ハッシュを作る words = ['hello', 'world', 'ruby'] lengths = words.inject({}) do |hash, word| hash[word] = word.length hash end p lengths # {"hello"=>5, "world"=>5, "ruby"=>4}
reduce は inject の別名です。
sum:合計を簡単に計算する
配列の合計には sum が最もシンプルです。
numbers = [1, 2, 3, 4, 5] p numbers.sum # 15 # ブロックで変換しながら合計 orders = [{ price: 100, qty: 2 }, { price: 200, qty: 1 }] total = orders.sum { |o| o[:price] * o[:qty] } p total # 400
group_by:グループ化する
items = [
{ name: 'apple', category: 'fruit' },
{ name: 'carrot', category: 'veggie' },
{ name: 'banana', category: 'fruit' },
]
grouped = items.group_by { |item| item[:category] }
p grouped
# { "fruit" => [...], "veggie" => [...] }
tally:出現回数を数える
tags = ['ruby', 'rails', 'ruby', 'js', 'ruby', 'rails'] p tags.tally # { "ruby" => 3, "rails" => 2, "js" => 1 }
flat_map:変換しながらフラット化する
sentences = ['hello world', 'foo bar'] # 単語の配列に分解 words = sentences.flat_map { |s| s.split } p words # ['hello', 'world', 'foo', 'bar'] # map だとネストが残る nested = sentences.map { |s| s.split } p nested # [['hello', 'world'], ['foo', 'bar']]
min / max / min_by / max_by
numbers = [3, 1, 4, 1, 5, 9, 2, 6] p numbers.min # 1 p numbers.max # 9 users = [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }, { name: 'Carol', age: 20 }] # 年齢が最も若いユーザー youngest = users.min_by { |u| u[:age] } p youngest # { name: 'Carol', age: 20 }
まとめ
| したいこと | 使うもの |
|---|---|
| 各要素を変換した配列を作る | map |
| 合計を計算する | sum |
| 集計・折りたたみ処理 | inject / reduce |
| グループ化する | group_by |
| 出現回数を数える | tally |
| 変換しながらフラット化 | flat_map |
| 最小・最大の要素を取り出す | min_by / max_by |
配列の絞り込みは「Ruby 配列の絞り込み:select・reject・find の使い方」を参照してください。
配列の繰り返し処理は「Ruby の繰り返し処理:each・times・map の使い分け」を参照してください。