如何在Ruby中求和数组的数字?

我有一个整数数组。

例如:

array = [123,321,12389]

有什么好方法能求出它们的和吗?

我知道

sum = 0
array.each { |a| sum+=a }

是可行的。

530518 次浏览

试试这个:

array.inject(0){ |sum, x| sum + x }

参见Ruby's Enumerable Documentation

(注意:需要0基本大小写,以便在空数组上返回0而不是nil)

对于ruby >= 2.4你可以使用总和:

# EYZ0

对于ruby <2.4你可以使用注入:

array.inject(0, :+)

注意:需要0基本大小写,否则在空数组上返回nil:

> [].inject(:+)
nil
> [].inject(0, :+)
0

或者(只是为了比较),如果你安装了Rails(实际上只有ActiveSupport):

require 'activesupport'
array.sum

对于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

还允许使用[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, :+)

虽然相当于array.inject(0, :+),但随着MapReduce编程模型的兴起,减少这个术语正在进入更常见的方言。

注入减少褶皱积累压缩都是折叠功能类的同义词。我发现代码库之间的一致性是最重要的,但由于各种社区倾向于使用一个词而不是另一个词,因此了解替代词是有用的。

为了强调map-reduce的冗余,这里有一个版本,它对数组中的内容更加宽容。

array.map(&:to_i).reduce(0, :+)

其他相关阅读:

  • < a href = " http://ruby-doc.org/core-1.9.3/Enumerable.html method-i-inject " > http://ruby-doc.org/core-1.9.3/Enumerable.html method-i-inject < / >
  • http://en.wikipedia.org/wiki/MapReduce < a href = " http://en.wikipedia.org/wiki/MapReduce " > < / >
  • (higher-order_function) < a href = " http://en.wikipedia.org/wiki/Fold_ " > http://en.wikipedia.org/wiki/Fold_ (higher-order_function) < / >

只是为了多样性,如果你的数组不是一个数字数组,而是一个具有数字属性的对象数组(例如amount),你也可以这样做:

array.inject(0){|sum,x| sum + x.amount}

你也可以用简单的方法做这件事

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

Ruby 2.4+ / Rails - array.sum,即[1, 2, 3].sum # => 6

Ruby pre 2.4 - array.inject(:+)array.reduce(:+)

*注意:#sum方法是2.4中为enumerable添加的新方法,所以你现在可以在纯ruby中使用array.sum,而不仅仅是Rails。

如果你想打高尔夫,你可以

eval [123,321,12389]*?+

这将创建一个字符串“123+321+12389”;然后用函数eval来求和。这是只是为了打高尔夫,你不应该在正确的代码中使用它。

Ruby 2.4.0发布了,它有一个可列举的#和方法。所以你可以

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是这样的更多信息,请参阅这个答案

方法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

# EYZ0

   [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

< >强方法六: 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+

对于nil值的数组,我们可以压缩,然后注入和 除< / p >

a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)