I have an array of integers.
For example:
array = [123,321,12389]
Is there any nice way to get the sum of them?
I know, that
sum = 0
array.each { |a| sum+=a }
would work.
I have an array of integers.
For example:
array = [123,321,12389]
Is there any nice way to get the sum of them?
I know, that
sum = 0
array.each { |a| sum+=a }
would work.
Try this:
array.inject(0){|sum,x| sum + x }
See Ruby\'s Enumerable Documentation
(note: the 0
base case is needed so that 0
will be returned on an empty array instead of nil
)
Or try the Ruby 1.9 way:
array.inject(0, :+)
Note: the 0
base case is needed otherwise nil
will be returned on empty arrays:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.reduce(0, :+)
While equivalent to array.inject(0, :+)
, the term reduce is entering a more common vernacular with the rise of MapReduce programming models.
inject, reduce, fold, accumulate, and compress are all synonymous as a class of folding functions. I find consistency across your code base most important, but since various communities tend to prefer one word over another, it’s nonetheless useful to know the alternatives.
To emphasize the map-reduce verbiage, here’s a version that is a little bit more forgiving on what ends up in that array.
array.map(&:to_i).reduce(0, :+)
Some additional relevant reading:
Alternatively (just for comparison), if you have Rails installed (actually just ActiveSupport):
require \'activesupport\'
array.sum
It is dangerous to mokeypatch base classes and now that Ruby 2.4.0 has sum on Enumerables it is not needed and dangerous. If you like danger and using an older version of Ruby, you could add #sum
to the Array
class:
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
Then do fun stuff like:
[1, 2, 3, 4].sum
You can use the aptly named method Enumerable#sum
. It has a lot of advantages over inject(:+)
but there are some important notes to read at the end as well.
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
This method is not equivalent to #inject(:+)
. For example
%w(a b c).inject(:+)
#=> \"abc\"
%w(a b c).sum
#=> TypeError: String can\'t be coerced into Integer
Also,
(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)
See this answer for more information on why sum
is like this.
Just for the sake of diversity, you can also do this if your array is not an array of numbers, but rather an array of objects that have properties that are numbers (e.g. amount):
array.inject(0){|sum,x| sum + x.amount}
ruby 1.8.7 way is the following:
array.inject(0, &:+)
Ruby 2.4+ / Rails - array.sum
i.e. [1, 2, 3].sum # => 6
Ruby pre 2.4 - array.inject(:+)
or array.reduce(:+)
*Note: The #sum
method is a new addition to 2.4 for enumerable
so you will now be able to use array.sum
in pure ruby, not just Rails.
You can simply use:
example = [1,2,3]
example.inject(:+)
This is Enough
[1,2,3].inject(\'+\')
Also allows for [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 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
for array with nil values we can do compact and then inject the sum ex-
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
array.reduce(:+)
Works for Ranges too... hence,
(1..10).reduce(:+) returns 55
Method 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
Method 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 `+\'
Method 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 `+\'
Method 4: When Array contains an nil and empty values, by default if you use any above functions reduce, sum, inject everything will through the
TypeError: nil can\'t be coerced into Integer
You can overcome this by,
[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
Method 6: eval
Evaluates the Ruby expression(s) in string.
[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+
If you feel golfy, you can do
eval([123,321,12389]*?+)
This will create a string \"123+321+12389\" and then use function eval to do the sum. This is only for golfing purpose, you should not use it in proper code.
You could also use recursion
def sum(array)
array.length == 1 ? array.pop() : array.pop() + sum(array)
end
if you don\'t want to be destructive, make a clone.
Or you can try this method:
def sum arr
0 if arr.empty
arr.inject :+
end
This is the shortest way. Try it.
array.inject :+
You can also do it in easy way
def sum(numbers)
return 0 if numbers.length < 1
result = 0
numbers.each { |num| result += num }
result
end
You can use .map and .sum like:
array.map { |e| e }.sum