У мене є масив цілих чисел.
Наприклад:
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