Enumerableで定義されている配列の抽出・検索について書いたのですが、Enumerableには配列の値操作についてもいろいろ便利なものがあるので、それらをまとめてみました。
map / collect
各要素に対して{}ブロック内の 式を実行した結果 を返します。
collect
は map
と同義です。
# すべて3倍にして返す
[1, 2, 3].map { |n| n * 3 }
# => [3, 6, 9]
reduce / inject
各要素に対して{}ブロック内の式を順次実行し、最後までのブロックの実行結果 を返します。
ブロックパラメータ(||で囲まれた箇所)の1つ目には前回の実行結果が入り、2つ目のパラメータには次の要素が入ります。
inject
は reduce
と同義です。
# 配列の合計を求める
[1, 2, 3, 4, 5].inject { |result, item| result + item }
# => 15
# ちなみにブロックパラメータにはこんな感じで値が設定される
# 1回目のループ … |要素1, 要素2|
# 2回目のループ … |前回の結果, 要素3|
# 3回目のループ … |前回の結果, 要素4|
# 4回目のループ … |前回の結果, 要素5|
# 最大値を求める
[1, 2, 3, 4, 5].inject { |max, item| item > max ? item : max }
# => 5
初期値はこう書くと設定できます。
# 初期値を10として、配列の合計を求める
[1, 2, 3, 4, 5].inject(10) { |result, item| result + item }
# => 25
group_by
{}ブロック内の式の 結果をキー、対応する要素の配列を値 とするハッシュを返します。
#奇数と偶数でグループ分けする
[1, 2, 3, 4, 5, 6].group_by { |i| i % 2 }
# => {1 => [1, 3, 5], 0 => [2, 4, 6]}
なので、結果がboolになる式の場合はキーがtrue/falseになります。
chunk
{}ブロック内の 式の結果ごとに要素をまとめた 配列を返します。
戻り値はEnumeratorオブジェクトなので、eachなどを使うことで中身を取得できます。
[3, 1, 4, 1, 5, 9, 2, 6].chunk { |n| n % 2 == 0 ? :even : :odd }.each { |key, value| p [key, value]}
# => [:odd, [3, 1]]
# [:even, [4]]
# [:odd, [1, 5, 9]]
# [:even, [2, 6]]
注意が必要なのは、式の結果が変わったタイミングで要素のグルーピングが切り替わるという点です。
また、{}ブロック内でnilを返すと、その要素は含まれなくなります。
[3, 1, 4, 1, 5, 9, 2, 6].chunk { |n| n % 2 == 0 ? :even : nil }.each { |key, value| p [key, value]}
# => [:even, [4]]
# [:even, [2, 6]]
sort_by
{}ブロック内の式の結果を <=> 演算子で比較し、昇順にソート します。
# 文字を昇順にソートする
p ["foo", "bar", "Baz", "Qux"].sort_by { |v| v.downcase }
# => ["bar", "Baz", "foo", "Qux"]
# こうすれば数字を降順にソートできる
p [1, 5, 7, 2, 4, 9].sort_by { |v| v * -1 }
# => [9, 7, 5, 4, 2, 1]
まとめ
Enumerable#lazyなど、ここでは書ききれないメソッドはまだまだあったりします。
なのでドキュメントをみることをおすすめします!
Rubyってクラス探訪するだけで面白いですね。