605

我有一个整数数组。

例如:

array = [123,321,12389]

有什么好方法可以得到它们的总和吗?

我知道

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

会工作。

4

16 回答 16

834

对于 ruby​​ >= 2.4,您可以使用sum

array.sum

对于 ruby​​ < 2.4,您可以使用inject

array.inject(0, :+)

注意:0需要基本情况​​,否则nil将在空数组上返回:

> [].inject(:+)
nil
> [].inject(0, :+)
0
于 2009-10-08T16:28:13.253 回答
641

尝试这个:

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

查看 Ruby 的可枚举文档

(注意:0需要基本情况​​,以便0将返回一个空数组而不是nil

于 2009-10-08T16:07:04.170 回答
302
array.reduce(0, :+)

虽然等同于array.inject(0, :+),但随着MapReduce 编程模型的兴起,reduce一词正在进入一个更常见的术语。

injectreducefoldaccumulatecompress都是折叠函数的同义词。我发现您的代码库的一致性最重要,但由于各种社区倾向于使用一个词而不是另一个词,因此了解替代词仍然很有用。

为了强调 map-reduce 的措辞,这里有一个版本,它对数组中的结果更加宽容。

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

一些额外的相关阅读:

于 2012-12-14T17:06:59.070 回答
117

或者(仅用于比较),如果您安装了 Rails(实际上只是 ActiveSupport):

require 'activesupport'
array.sum
于 2009-10-08T16:49:10.013 回答
91

对于 Ruby >=2.4.0,您可以使用sumEnumerables。

[1, 2, 3, 4].sum

mokeypatch 基类是危险的。如果你喜欢危险并使用旧版本的 Ruby,你可以添加#sumArray类中:

class Array
  def sum
    inject(0) { |sum, x| sum + x }
  end
end
于 2009-10-08T18:29:42.447 回答
51

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

于 2017-01-04T03:33:18.550 回答
22

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

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

*注意:该#sum方法是 2.4 的新增功能,enumerable因此您现在可以array.sum在纯 ruby​​ 中使用,而不仅仅是在 Rails 中使用。

于 2016-06-09T08:38:59.183 回答
19

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

array.inject(0){|sum,x| sum + x.amount}
于 2013-07-24T14:23:14.050 回答
18

ruby 1.8.7 方式如下:

array.inject(0, &:+) 
于 2011-06-22T15:56:41.163 回答
5

Ruby 2.4.0 is released, and it has an Enumerable#sum method. So you can do

array.sum

Examples from the docs:

{ 1 => 10, 2 => 20 }.sum {|k, v| k * v }  #=> 50
(1..10).sum                               #=> 55
(1..10).sum {|v| v * 2 }                  #=> 110
于 2016-12-19T12:20:18.753 回答
4

对于具有 nil 值的数组,我们可以进行压缩,然后注入总和 ex-

a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
于 2018-05-03T04:36:13.120 回答
3

还允许[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
于 2011-01-30T08:06:13.670 回答
2

如果你觉得高尔夫,你可以做

eval [123,321,12389]*?+

这将创建一个字符串“123+321+12389”,然后使用函数 eval 进行求和。这仅用于打高尔夫球的目的,您不应该在正确的代码中使用它。

于 2016-11-27T20:24:11.467 回答
2

方法一:

    [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

方法二:

   [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 `+'

方法三:

   [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+
于 2018-02-01T11:51:57.813 回答
-1

你也可以用简单的方法做到这一点

def sum(numbers)
  return 0 if numbers.length < 1
  result = 0
  numbers.each { |num| result += num }
  result
end
于 2014-12-12T14:27:45.437 回答
-10

您可以使用.map.sum ,例如:

array.map { |e| e }.sum
于 2015-07-23T20:16:29.503 回答