Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

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

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