Edited at

mapなどの配列の値を操作するメソッドまとめ

More than 3 years have passed since last update.

Enumerableで定義されている配列の抽出・検索について書いたのですが、Enumerableには配列の値操作についてもいろいろ便利なものがあるので、それらをまとめてみました。


map / collect

各要素に対して{}ブロック内の 式を実行した結果 を返します。

collectmap と同義です。

# すべて3倍にして返す

[1, 2, 3].map { |n| n * 3 }
# => [3, 6, 9]


reduce / inject

各要素に対して{}ブロック内の式を順次実行し、最後までのブロックの実行結果 を返します。

ブロックパラメータ(||で囲まれた箇所)の1つ目には前回の実行結果が入り、2つ目のパラメータには次の要素が入ります。

injectreduce と同義です。

# 配列の合計を求める

[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ってクラス探訪するだけで面白いですね。