或るプログラマの開発日記

日々の勉強したことの備忘録なんかに使っていきます

Rubyのinject/reduceメソッドに関するメモ

つい最近までRubyのinjectやらreduceが何してるか分からんかったので調査したことをメモ。

inject/reduceメソッド

injectメソッドは、ブロックを使って繰り返し計算を行うのに使います。ブロックに順に「要素1、要素2」、「ブロックの前回の戻り値、要素3」、「ブロックの前回の戻り値、要素4」、...を渡します。メソッドの戻り値はブロックが最後に返した値になります。

http://ref.xaio.jp/ruby/classes/enumerable/inject

イメージとしては、ハッシュや配列(要はEnumerableオブジェクト)の各要素に対して繰り返し処理を行い一つに纏めた結果を返す処理に使うものかなーという感じです。

因みにreduceは、injectメソッドの別名となります。mapとcollectの関係みたいなものですね。

使い方いろいろ

injectメソッドの使用例として、配列の合計を求める方法が良く使われます。
以下、サンプルとしていろんな書き方を試してみました。

array = (1..20).to_a

p array.inject {|sum, n| sum + n }#=>210
p array.inject(0){|sum, n| sum + n }#=>210
p array.inject(0,:+)#=>210
p array.inject(:+)#=>210

#100を初期値にしてみる
p array.inject(100,:+)#=>310

injectの書き方にもブロックで要素を処理する方法や、初期値を指定または省略する方法、またメソッドの引数でシンボルを渡して処理する方法があります。

また、配列の合計を計算する以外の使い方もあります。

次の例では初期値を空のハッシュで定義し、レシーバの配列から条件に合致する値のみを追加したハッシュを返す処理を行っています。初期値を配列にすれば、結果を配列で返すことも可能です。

array = (1..10).to_a.reduce({}) do |arr, item |
  arr << item if item % 2 == 0
  arr
end

p array
#=>{2=>true, 4=>true, 6=>true, 8=>true, 10=>true}

工夫次第で、配列周りの処理を簡潔に記述できそうですね。

参考URL

reduceやinjectという名称と処理のイメージが中々結び付かなかったのですが、以下のURLの記事の説明がなかなか分かりやすかったです。
Rubyist Magazine - map と collect、reduce と inject ―― 名前の違いに見る発想の違い