Ответ 1
Попробуйте это:
array.inject(0){|sum,x| sum + x }
См. перечислимую документацию по Ruby
.(примечание: базовый случай 0
необходим для того, чтобы 0
возвращался в пустом массиве вместо nil
)
У меня есть массив целых чисел.
Например:
array = [123,321,12389]
Есть ли хороший способ получить их сумму?
Я знаю, что
sum = 0
array.each { |a| sum+=a }
будет работать.
Попробуйте это:
array.inject(0){|sum,x| sum + x }
См. перечислимую документацию по Ruby
.(примечание: базовый случай 0
необходим для того, чтобы 0
возвращался в пустом массиве вместо nil
)
Или попробуйте Ruby 1.9:
array.inject(0, :+)
Примечание: необходим базовый регистр 0
, иначе nil
будет возвращен на пустые массивы:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.reduce(0, :+)
В то время как эквивалент array.inject(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, вы можете добавить #sum
в класс Array
:
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
Вы можете использовать метод aptly named 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.inject(0){|sum,x| sum + x.amount}
Ruby 2.4+/Rails - array.sum
i.e. [1, 2, 3].sum # => 6
Ruby pre 2.4 - array.inject(:+)
или array.reduce(:+)
* Примечание. Метод #sum
является новым дополнением к 2.4 для enumerable
, поэтому теперь вы сможете использовать array.sum
в чистом рубине, а не только в Rails.
ruby 1.8.7 путь следующий:
array.inject(0, &:+)
Вы можете просто использовать:
example = [1,2,3]
example.inject(:+)
Этого достаточно [1,2,3].inject('+')
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
Также позволяет [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
для массива с нулевыми значениями мы можем сделать компакт и затем ввести сумму ex-
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
array.reduce(:+)
Работает для Диапазоны тоже... следовательно,
(1..10).reduce(:+) returns 55
Если вы чувствуете игру в гольф, вы можете сделать
eval([123,321,12389]*?+)
Это создаст строку "123 + 321 + 12389", а затем воспользуемся функцией eval для выполнения суммы. Это только для игры в гольф, вы не должны использовать его в правильном коде.
Вы также можете использовать рекурсию
def sum(array)
array.length == 1 ? array.pop() : array.pop() + sum(array)
end
Если вы не хотите быть разрушительным, сделайте клон.
Способ 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 не может быть приведен к 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: 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+
Или вы можете попробовать этот метод:
def sum arr
0 if arr.empty
arr.inject :+
end
Это самый короткий путь. Попытайся.
array.inject :+
number = [1..100]
number. each do |n|
final_number = n.sum
puts "The sum is #{final_number}"
end
* Это хорошо работает для меня, как нового разработчика. Вы можете настроить свой диапазон номеров, изменив значения в пределах []
Вы также можете сделать это простым способом
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