回答:
array.inject(:+)
方が効率的です。
array.inject(:+)
Ruby 1.8.6で問題が発生するようです。例外「LocalJumpError:ブロックが指定されていません」がポップアップする場合があります。
array.sum
では、配列の値の合計が得られる場合があります。
reduce
エイリアスであるを使用することを好みます。inject
array.reduce( :+ )
inject
ではなくを使用するよう警告しますreduce
。
またはRuby 1.9の方法を試してください:
array.inject(0, :+)
注:0
基本ケースが必要です。それ以外の場合はnil
空の配列で返されます。
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.map(&:price).inject(0, :+)
少し安全です。空のリストがある場合は、nilの代わりに0を取得します。
array.inject(0) { |sum, product| sum += product.price }
array.reduce(0, :+)
と同じですがarray.inject(0, :+)
、reduceという用語は、MapReduceプログラミングモデルの登場により、より一般的な用語になりつつあります。
inject、reduce、fold、accumulate、compressはすべて、折りたたみ関数のクラスと同じ意味です。私はコードベース全体の一貫性が最も重要であると考えていますが、さまざまなコミュニティが1つの単語を別の単語よりも好む傾向があるため、代替案を知ることは役に立ちます。
map-reduceの言い回しを強調するために、その配列で最終的に何が発生するかを少し許容するバージョンを次に示します。
array.map(&:to_i).reduce(0, :+)
追加の関連する読み物:
reduce
ます、関数が何をするかについてもっと教えてくれますが、inject
はるかにクールに聞こえます。
reduce
とmap
高階関数は、MapReduceのをさかのぼるよう。インスピレーションは逆に実行されます。MapReduceの意味では、これは単純な機能的な削減とはやや異なる操作であり、さまざまなマシンの通信方法に影響を与えます。
別の方法として(比較のため)、Railsがインストールされている場合(実際にはActiveSupportのみ):
require 'activesupport'
array.sum
require 'active_support/core_ext/enumerable.rb'
、アクティブなサポートをすべて必要とする必要がありますrequire 'active_support/all'
。詳細はこちら:API Docs
activesupport
であることを気にしないでください。array.inject(:+)
array.sum
require 'active_support/core_ext/enumerable'
、.rb
サフィックスを付けないでください。
Ruby> = 2.4.0の場合sum
、Enumerablesから使用できます。
[1, 2, 3, 4].sum
基本クラスをmokeypatchするのは危険です。危険が気になり、古いバージョンのRubyを使用する場合は#sum
、Array
クラスに追加できます。
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
適切な名前のメソッドを使用できますEnumerable#sum
。それには多くの利点inject(:+)
がありますが、最後に読むべきいくつかの重要な注意事項もあります。
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
このメソッドはと同等ではありません#inject(:+)
。例えば
%w(a b c).inject(:+)
#=> "abc"
%w(a b c).sum
#=> TypeError: String can't be coerced into Integer
また、
(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)
多様性のために、配列が数値の配列ではなく、数値(たとえば、金額)のプロパティを持つオブジェクトの配列である場合にも、これを行うことができます。
array.inject(0){|sum,x| sum + x.amount}
array.map(&:amount).inject(0, :+)
。他の回答を参照してください。
map
then を使用inject
すると、配列を2回ループする必要があります。1つは新しい配列を作成するため、もう1つはメンバーを合計するためです。この方法は少し冗長ですが、より効率的です。
ruby 1.8.7の方法は次のとおりです。
array.inject(0, &:+)
あなたは単に使うことができます:
example = [1,2,3]
example.inject(:+)
inject(:+)
しかし、これはそうではありませんかinject :+
?
Ruby 2.4.0がリリースされ、Enumerable#sumメソッドが追加されました。だからできる
array.sum
ドキュメントの例:
{ 1 => 10, 2 => 20 }.sum {|k, v| k * v } #=> 50
(1..10).sum #=> 55
(1..10).sum {|v| v * 2 } #=> 110
また、次のことが可能です[1,2].sum{|x| x * 2 } == 6
。
# http://madeofcode.com/posts/74-ruby-core-extension-array-sum
class Array
def sum(method = nil, &block)
if block_given?
raise ArgumentError, "You cannot pass a block and a method!" if method
inject(0) { |sum, i| sum + yield(i) }
elsif method
inject(0) { |sum, i| sum + i.send(method) }
else
inject(0) { |sum, i| sum + i }
end
end
end
値がnilの配列の場合、コンパクトにしてから合計を注入できます。
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
方法1:
[1] pry(main)> [1,2,3,4].sum
=> 10
[2] pry(main)> [].sum
=> 0
[3] pry(main)> [1,2,3,5,nil].sum
TypeError: nil can't be coerced into Integer
方法2:
[24] pry(main)> [].inject(:+)
=> nil
[25] pry(main)> [].inject(0, :+)
=> 0
[4] pry(main)> [1,2,3,4,5].inject(0, :+)
=> 15
[5] pry(main)> [1,2,3,4,nil].inject(0, :+)
TypeError: nil can't be coerced into Integer
from (pry):5:in `+'
方法3:
[6] pry(main)> [1,2,3].reduce(:+)
=> 6
[9] pry(main)> [].reduce(:+)
=> nil
[7] pry(main)> [1,2,nil].reduce(:+)
TypeError: nil can't be coerced into Integer
from (pry):7:in `+'
方法4: Arrayにnilと空の値が含まれている場合、デフォルトで上記の関数を使用すると、reduce、sum、injectすべてが
TypeError:nilはIntegerに強制変換できません
これを克服できます
[16] pry(main)> sum = 0
=> 0
[17] pry(main)> [1,2,3,4,nil, ''].each{|a| sum+= a.to_i }
=> [1, 2, 3, 4, nil, ""]
[18] pry(main)> sum
=> 10
方法6: 評価
文字列内のRuby式を評価します。
[26] pry(main)> a = [1,3,4,5]
=> [1, 3, 4, 5]
[27] pry(main)> eval a.join '+'
=> 13
[30] pry(main)> a = [1,3,4,5, nil]
=> [1, 3, 4, 5, nil]
[31] pry(main)> eval a.join '+'
SyntaxError: (eval):1: syntax error, unexpected end-of-input
1+3+4+5+
あなたも簡単な方法でそれを行うことができます
def sum(numbers)
return 0 if numbers.length < 1
result = 0
numbers.each { |num| result += num }
result
end
次のように.mapと.sumを使用できます。
array.map { |e| e }.sum
array.sum
array.sum