2009/01/14(Wed)
ruby の inject をわかりやすく説明してみる
ruby の inject って慣れないと少し理解しづらいよなーと思ったので、極力わかりやすい説明をしてみるテスト。
わかりやすいかもしれない説明
さて、1 から 10 までの合計を求めるこんな↓コードがあった場合
sum = 0 (1..10).each {|i| sum = sum + i } p sum # => 55
inject を使ってこのよう↓に書けます。
p (1..10).inject(0) {|sum, i| sum + i }
each と inject でどのように書き変わってるかを図で示すとこんな↓感じ。
injectの引数 0 は、ブロックローカルな sum 変数の初期値になってます。で、ブロックの実行結果の値が sum に代入されて、2回目以降のループを実行します。ループしている間の、各変数とブロックの中身はこんな↓感じ。
| sum | i | ブロックの中身(sum + i) | の実行結果 |
|---|---|---|---|
| 0 | 1 | 0 + 1 | = 1 |
| 1 | 2 | 1 + 2 | = 3 |
| 3 | 3 | 3 + 3 | = 6 |
| 6 | 4 | 6 + 4 | =10 |
| 10 | 5 | 10 + 5 | =15 |
| 15 | 6 | 15 + 6 | =21 |
| 21 | 7 | 21 + 7 | =28 |
| 28 | 8 | 28 + 8 | =36 |
| 36 | 9 | 36 + 9 | =45 |
| 45 | 10 | 45 + 10 | =55 |
最後に実行されたブロックの結果が、inject の戻り値となります。
よくあるパターン
んじゃ、inject で書き換える事ができる他のパターンを見てみます
フィボナッチ数列を求める
こんな↓コードがあった場合
fib = [1, 1] (0..10).each {|i| fib << fib[i] + fib[i+1]} p fib # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
inject を使ってこのよう↓に書けます。
p (0..10).inject([1, 1]) {|fib, i| fib << fib[i] + fib[i+1] }
あるデータの度数分布を求める
こんな↓コードがあった場合
data = [:A, :B, :A, :C, :E, :A, :D, :B, :B, :C, :E] h = Hash.new(0) data.each {|key| h[key] += 1 } p h # => {:A=>3, :B=>3, :C=>2, :E=>2, :D=>1}
inject を使ってこのよう↓に書けます。
data = [:A, :B, :A, :C, :E, :A, :D, :B, :B, :C, :E] p data.inject(Hash.new(0)) {|h, key| h[key] += 1; h }
上の例の場合、ブロックの実行結果でハッシュ(h)を返したいので、セミコロンで区切って h を返しています。
まとめ
どの例でも、ループで計算した結果を保持しとく変数が、inject では、ブロックローカルな変数で済んでるのでスッキリした感じがしますね。そんなわけで、皆で inject厨になりましょう。
トラックバック - http://d.hatena.ne.jp/kenkitii/20090114/ruby_inject
リンク元
- 24 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=org.mozilla:ja:official&hs=ZjL&q=cpan+upgrade+force&btnG=検索&lr=lang_ja
- 16 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4DAJP_jaJP276JP276&q=ruby++++av
- 12 http://www.google.co.jp/search?hl=ja&lr=lang_ja&client=firefox-a&rls=org.mozilla:ja:official&hs=g8F&q=cpan+upgrade&start=10&sa=N
- 12 http://www.google.com/search?hl=ja&lr=lang_ja&ie=UTF-8&oe=UTF-8&q=ruby+rack&num=50
- 9 http://www.google.co.jp/search?q=ds+homebrew&lr=lang_ja&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja-JP-mac:official&client=firefox-a
- 8 http://d.hatena.ne.jp
- 8 http://ezsch.ezweb.ne.jp/search/ezGoogleMain.php?query=AV女優一覧&start-index=4&adpage=3&mode=02
- 6 http://d.hatena.ne.jp/ramyana/20070529/1180431058
- 6 http://ezsch.ezweb.ne.jp/search/ezGoogleMain.php?query=AV女優+一覧&start-index=4&adpage=3&mode=02
- 6 http://images.google.co.jp/imgres?imgurl=http://d.hatena.ne.jp/images/diary/k/kenkitii/2004-09-13.jpg&imgrefurl=http://d.hatena.ne.jp/kenkitii/20040913&usg=__acp4tcyi0eCMVdVJPj7cJDhPYnI=&h=102&w=150&sz=7&hl=ja&start=24&um=1&tbnid=pyzQ6-GSZXTyIM:&tbnh=65&t

