У мене є масив цілих чисел.
Наприклад:
array = [123,321,12389]
Чи є якийсь приємний спосіб отримати суму їх?
Я знаю це
sum = 0
array.each { |a| sum+=a }
працювали б.
У мене є масив цілих чисел.
Наприклад:
array = [123,321,12389]
Чи є якийсь приємний спосіб отримати суму їх?
Я знаю це
sum = 0
array.each { |a| sum+=a }
працювали б.
Відповіді:
Спробуйте це:
array.inject(0){|sum,x| sum + x }
Див. Перелічену документацію Рубі
(зверніть увагу: 0базовий регістр потрібен, щоб 0він повертався на порожній масив замість nil)
array.inject(:+)є більш ефективним.
array.inject(:+)Схоже, це спричинить проблеми в Ruby 1.8.6 Виключення "LocalJumpError: не вказано блоку" може спливати.
array.sumможе бути вказана сума значень масиву.
reduce, що є псевдонімом inject(як у array.reduce( :+ )).
injectа не reduce.
Або спробуйте Ruby 1.9 способом:
array.inject(0, :+)
Примітка: 0базовий регістр необхідний, інакше nilповернеться на порожні масиви:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.map(&:price).inject(0, :+)трохи безпечніше. Це гарантує, що якщо у вас порожній список, ви отримуєте 0 замість нуля .
array.inject(0) { |sum, product| sum += product.price }
array.reduce(0, :+)
Незважаючи на те array.inject(0, :+), що термін " скорочення" входить до більш поширеної мови з підйомом моделей програмування MapReduce .
введення , зменшення , складання , накопичення та стиснення - всі синоніми як клас функцій складання . Я вважаю, що послідовність у вашій базі коду є найважливішою, але оскільки різні громади, як правило, віддають перевагу одному слову над іншим, тим не менш корисно знати альтернативи.
Щоб підкреслити багатослівне зменшення карт, ось версія, яка трохи прощає те, що опиняється в цьому масиві.
array.map(&:to_i).reduce(0, :+)
Деякі додаткові відповідні читання:
reduceрозповідає мені більше того, що робить функція, але injectзвучить набагато крутіше.
reduceі mapв функції вищого порядку передує MapReduce. Натхнення працює іншим шляхом. І в сенсі MapReduce, це дещо інша операція, ніж просте функціональне зменшення, що має наслідки для того, як спілкуються різні машини.
Як варіант (лише для порівняння), якщо у вас встановлено Rails (насправді лише ActiveSupport):
require 'activesupport'
array.sum
require 'active_support/core_ext/enumerable.rb'або вимагати все активної підтримки: require 'active_support/all'. Більше про це тут: API Документи
activesupportце масивне залежність перетягнути в проект , щоб перейти від array.inject(:+)до array.sum.
require 'active_support/core_ext/enumerable'без .rbсуфікса, оскільки це додається неявно.
Для 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
Ви можете використовувати влучно названий метод 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}
array.map(&:amount).inject(0, :+). Дивіться інші відповіді.
mapцього injectвимагає провести цикл через масив двічі: один раз для створення нового масиву, інший для підсумовування членів. Цей метод трохи більш багатослівний, але також більш ефективний.
Ruby 2.4+ / Рейки - array.sumтобто[1, 2, 3].sum # => 6
Рубін попередньо 2,4 - array.inject(:+)абоarray.reduce(:+)
* Примітка. #sumМетод є новим доповненням до версії 2.4 для, enumerableтому тепер ви зможете використовувати array.sumв чистому рубіні, а не лише на Rails.
Рубін 1.8.7 спосіб такий:
array.inject(0, &:+)
Ви можете просто використовувати:
example = [1,2,3]
example.inject(:+)
inject(:+)але це не так 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
Спосіб 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+
Це найкоротший шлях. Спробуй це.
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
array.sum
array.sum