Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

Active_support提供のEnumerable#sumで合算時に楽をする

Active_support提供のEnumerable#sumで合算時に楽をできるメソッドです

使い方

[1,2,3].sum
#=> 6

(1..100).sum
#=> 5050

ブロックを渡して、ちょっと入り組んだ合算をやる事も可能です。
下の例では、各要素の二倍を合算する例を挙げています。

(1..2).sum {|n| n * 2 }
=> 6

文字列も同じように合算対象となります。

%w(as you like).sum
=> "asyoulike"

%w(as you like).sum {|i| " " << i }
=> " as you like"

%w(as you like).sum {|i| " " << i.upcase }
=> " AS YOU LIKE"

実装

実装内容は

module Enumerable
  def sum(identity = 0, &block)
    if block_given?
      map(&block).sum(identity)
    else
      inject { |sum, element| sum + element } || identity
    end
  end
end

class Range #:nodoc:
  # Optimize range sum to use arithmetic progression if a block is not given and
  # we have a range of numeric values.
  def sum(identity = 0)
    if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer))
      super
    else
      actual_last = exclude_end? ? (last - 1) : last
      if actual_last >= first
        (actual_last - first + 1) * (actual_last + first) / 2
      else
        identity
      end
    end
  end
end

と、またしても再帰を使ったコワイ実装になっています。