はじめに
配列要素を集計したいときの書き方をいくつかまとめました。
次のようなユーザー配列について、出身地別のユーザー数を求めることを考えます。
# 集計したいユーザー配列
user_list = [
{ user_id: 1, hometown: '東京都' },
{ user_id: 2, hometown: '大阪府' },
{ user_id: 3, hometown: '東京都' },
{ user_id: 4, hometown: '北海道' },
{ user_id: 5, hometown: '大阪府' },
{ user_id: 6, hometown: '東京都' }
]
# 出身地ごとの人数を次のようにハッシュにまとめたい
{"東京都"=>3, "大阪府"=>2, "北海道"=>1}
※ サンプルコードの実行環境
$ ruby --version
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]
方法1: 手続き的に書く
result = {}
user_list.each do |user|
result[user[:hometown]] ||= 0
result[user[:hometown]] += 1
end
result
# => {"東京都"=>3, "大阪府"=>2, "北海道"=>1}
もう少しRubyらしく書きたいですね。
方法2: group_by
を使う
user_list.group_by { |user| user[:hometown] }.transform_values(&:length)
# => {"東京都"=>3, "大阪府"=>2, "北海道"=>1}
最初に空ハッシュを用意する必要がなくなり簡潔な記述になりました。
方法3: tally
を使う
user_list.map { |user| user[:hometown] }.tally
# => {"東京都"=>3, "大阪府"=>2, "北海道"=>1}
Ruby2.7で追加された比較的新しいメソッドであるEnumerable#tally
を使ってシンプルに記述することもできます。