Hack Your Design!

Ruby の inject メソッドを使いこなす

Rubyのイテレータメソッドinjectの使い方を紹介してみようと思います。

injectの基本的な使い方

Rubyのinjectはこんなふうに使えます。

enum.inject {|memo, item| block }
enum.inject(init) {|memo, item| block }

Sum(合計)を出す

これだけではわかりにくいと思うので合計を出す処理を書いてみましょう。

まずはinjectを使わないパターン。

sum = 0
(1..10).each {|i| sum += i }
puts sum # => 55

これをinjectで書き直すとこう。

(1..10).inject {|sum, i| sum += i }
# => 55

この場合、sumの初期値は0ですがそれを明示的にかくならこう。

(1..10).inject(0) {|sum, i| sum += i }
# => 55

さらにinjectにはシンボルで演算子をわたしてうまいようにやってくれる。

(1..10).inject(:+)
# => 55

これが一番シンプルでエレガント。

応用編1: 配列内の要素数をハッシュに

Hash.new(0)で初期化してinject.

[:great, :good, :bad, :good, :good, :bad, :awesome, :great].inject(Hash.new(0)) {|hash, key| hash[key] += 1; hash}
# => {:great=>2, :good=>3, :bad=>2, :awesome=>1}

each_with_object を使う

上記の例だとhash[key] += 1; hashとやや冗長な書き方となっていますが、each_with_object使うともう少しシンプルに書けます。

[:great, :good, :bad, :good, :good, :bad, :awesome, :great].each_with_object(Hash.new(0)) {|key, hash| hash[key] += 1}
# => {:great=>2, :good=>3, :bad=>2, :awesome=>1}

応用編2: フィボナッチ数列

inject を利用したフィボナッチ数列ロジック。

(0..10).inject([1, 1]) {|fib, i| fib << fib[i] + fib[i+1] }
# => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]

番外編: each_with_index

each_with_indexでもinjectは使える。

(1..10).each_with_index.inject do |result, (element, index)|
  # ...
end

参考

  • このエントリーをはてなブックマークに追加
comments powered by Disqus