提问人:brainfck 提问时间:10/9/2009 最后编辑:Mab879brainfck 更新时间:9/13/2022 访问量:549525
如何在Ruby中对数字数组求和?
How to sum array of numbers in Ruby?
问:
我有一个整数数组。
例如:
array = [123,321,12389]
有什么好方法可以得到它们的总和吗?
我知道那件事
sum = 0
array.each { |a| sum+=a }
会起作用的。
答:
试试这个:
array.inject(0){ |sum, x| sum + x }
(注意:需要基本情况,以便将其返回到空数组而不是0
0
nil
)
评论
array.inject(:+)
array.inject(:+)
似乎在 Ruby 1.8.6 中引起了麻烦,可能会弹出“LocalJumpError : no block given”异常。
array.sum
reduce
inject
array.reduce( :+ )
inject
reduce
对于 ruby >= 2.4,您可以使用 sum:
array.sum
对于 ruby < 2.4,您可以使用 inject:
array.inject(0, :+)
注意:基本情况是必需的,否则将在空数组上返回:0
nil
> [].inject(:+)
nil
> [].inject(0, :+)
0
评论
array.map(&:price).inject(0, :+)
更安全一点。它确保如果你有一个空列表,你会得到 0 而不是 nil。
array.inject(0) { |sum, product| sum += product.price }
或者(只是为了比较),如果你安装了 Rails(实际上只是 ActiveSupport):
require 'activesupport'
array.sum
评论
require 'active_support/core_ext/enumerable.rb'
require 'active_support/all'
activesupport
array.inject(:+)
array.sum
require 'active_support/core_ext/enumerable'
.rb
对于 Ruby >=2.4.0,您可以从 Enumerables 中使用。sum
[1, 2, 3, 4].sum
mokeypatch 基类很危险。如果你喜欢危险,并且使用旧版本的 Ruby,你可以添加到类中:#sum
Array
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
评论
Array#sum
Array#sum
sum
Array
Money
Integer
array.sum( 0.to_money( "USD" ) )
还允许:[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
Ruby 1.8.7 的方式如下:
array.inject(0, &:+)
评论
array.reduce(0, :+)
虽然等同于,但随着MapReduce编程模型的兴起,术语reduce正在进入一个更常见的术语。array.inject(0, :+)
inject、reduce、fold、accumulate 和 compress 都是一类折叠函数的同义词。我发现代码库的一致性最为重要,但由于不同的社区倾向于更喜欢一个词而不是另一个词,因此了解替代方案仍然很有用。
为了强调 map-reduce 措辞,这里有一个版本,它对该数组中的最终内容更加宽容。
array.map(&:to_i).reduce(0, :+)
一些额外的相关阅读材料:
- http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-inject
- http://en.wikipedia.org/wiki/MapReduce
- http://en.wikipedia.org/wiki/Fold_(高order_function)
评论
reduce
inject
reduce
map
只是为了多样化,如果你的数组不是数字数组,而是具有数字属性(例如金额)的对象数组,你也可以这样做:
array.inject(0){|sum,x| sum + x.amount}
评论
array.map(&:amount).inject(0, :+)
map
inject
array.sum(&:amount)
您也可以以简单的方式完成
def sum(numbers)
return 0 if numbers.length < 1
result = 0
numbers.each { |num| result += num }
result
end
评论
inject
sum
您可以使用 .map 和 .sum,如下所示:
array.map { |e| e }.sum
评论
array.sum
Ruby 2.4+ / Rails - 即array.sum
[1, 2, 3].sum # => 6
Ruby 2.4 之前的版本 - 或array.inject(:+)
array.reduce(:+)
*注意:该方法是 2.4 的新增功能,因此您现在可以在纯 ruby 中使用,而不仅仅是 Rails。#sum
enumerable
array.sum
如果你觉得打高尔夫球,你可以做
eval [123,321,12389]*?+
这将创建一个字符串“123+321+12389”,然后使用函数 eval 进行求和。这仅用于高尔夫目的,您不应在适当的代码中使用它。
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
Ruby 2.4.0 的新功能
您可以使用恰如其分命名的方法。它有很多优点,但最后也有一些重要的注意事项需要阅读。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)
有关为什么会这样的更多信息,请参阅此答案。sum
评论
Array
Money
Integer
array.sum( 0.to_money( "USD" ) )
%w(a b c).sum # => "abc"
Array
Float
BigDecimal
.sum
Integer
foo.sum.to_f
方法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、in注入,一切都会通过
TypeError:nil 无法强制转换为整数
你可以通过以下方式克服这个问题,
[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:eval
计算字符串中的 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+
评论
reduce
从字面上看是一回事。如果你真的想自己构建一个对象,你应该考虑each_with_object
而不是(方法4)。建议:inject
each
[1,2,3,4,nil, ''].each_with_object(0) {|a| sum+= a.to_i }
对于具有 nil 值的数组,我们可以进行压缩,然后注入总和 前任-
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
评论
array.sum
Array
Money
Integer
array.sum( 0.to_money( "USD" ) )