Ruby 配列の変換・集計:map・inject・flat_map の使い方

スポンサーリンク

Ruby 配列の変換・集計:map・inject・flat_map の使い方

配列を別の形に変換したり、合計・グループ化したりするには mapinjectflat_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']

collectmap の別名です。


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}

reduceinject の別名です。


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 の使い分け」を参照してください。