У меня есть массив целых чисел.
Например:
array = [123,321,12389]
Есть ли какой-нибудь хороший способ получить их сумму?
Я знаю, что
sum = 0
array.each { |a| sum+=a }
сработает.
Попробуйте это:
array.inject(0){|sum,x| sum + x }
См. документацию Ruby's Enumerable Documentation
(примечание: базовый случай 0
необходим для того, чтобы 0
возвращалось в пустом массиве вместо nil
)
array.reduce(0, :+)
В то время как эквивалент массива.инъекционные(0, :+)
, термин сокращения входит более обычным языком с ростом модели программирования MapReduce.
вводить, сокращения, фолд, накапливать, и сжимать все синонимы как класс складывая функции. Я считаю, согласованность базы кода, самое важное, но с различными общинами, как правило, предпочитают одно слово за другим, он, тем не менее, полезно знать альтернативы.
Чтобы подчеркнуть карте-уменьшить словоблудие, вот версия, которая немного более снисходительными на то, что попадает в этот массив.
array.map(&:to_i).reduce(0, :+)
Некоторые дополнительные соответствующие значение:
В качестве альтернативы (просто для сравнения), если у вас установлен Rails (на самом деле просто ActiveSupport):
require 'activesupport'
array.sum
Для Ruby >=2.4.0 вы можете использовать sum
из Enumerables.
[1, 2, 3, 4].sum
Это опасно для mokeypatch базовых классов. Если вы любите опасность и используете старую версию Ruby, вы могли бы добавить #ГУУ
к массив
класса:
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
Вы можете использовать перечислимые метко назвал метод #сумма
. Она имеет много преимуществ по сравнению вложил (:+) но есть некоторые важные замечания, которые следует читать в конце, как хорошо.
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
Этот метод не является эквивалентом #впрыснуть(:+)
. Например
%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)
Смотрите этот ответ дополнительные сведения о том, почему сумма
, как это.
Руби 2.4+ / рельсы - массива.сумма
, т. е. [1, 2, 3].сумме # => 6
Руби до 2.4 - массива.впрыснуть (:+) или массива.функция reduce(:+)
*Примечание: #сумма метод-это новое дополнение к 2.4 для
перечислить`, так что вы теперь сможете использовать массив.сумма в чистого Рубина, а не просто рельсы.
Вы можете просто использовать:
example = [1,2,3]
example.inject(:+)
Этого вполне достаточно
[1,2,3].впрыснуть('+')
Руби 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
Также позволяет [1,2].сумма{|х| х * 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
Если вы чувствуете golfy, вы можете сделать
eval([123,321,12389]*?+)
Это позволит создать строку "и я 123+321+12389&; а затем использовать функцию eval, чтобы сделать сумму. Это только для целей игры в гольф, вы не должны использовать его в правильный код.
Способ 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: Когда массив содержит нулевые и пустые значения, по умолчанию, если вы используете любой из вышеупомянутых функций, снизить, сумму, вкачать все будет путем
ошибку 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: ивал
Вычисляет выражение Рубин(ов) в строке.
[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+
3 способа мы можем сделать сумма массива
массив.впрыснуть(0){|Сум,х| сумма + х }
массива.впрыснуть('+')
массива.присоединяйтесь('+')
Или вы можете попробовать этот метод:
def sum arr
0 if arr.empty
arr.inject :+
end
Это самый короткий путь. Попробуйте его.
массива.впрысните :+