Как я могу использовать этот способ для суммирования атрибута из объекта. Мой массив [product1, product2] Я хочу суммировать product1.price + product2.price. Возможно ли использовать array.inject (: +)?
Пабло Кантеро
7
Подобный прием можно использовать с методом карты: array.map (&: price) .inject (: +)
markquezada
100
array.map(&:price).inject(0, :+)немного безопаснее Это гарантирует, что если у вас есть пустой список, вы получите 0, а не ноль .
Джон
11
использование array.map (...). inject (...) неэффективно, вы будете перебирать все данные дважды. Попробуйте array.inject(0) { |sum, product| sum += product.price }
В то время как эквивалент array.inject(0, :+), термин сокращение входит в более общеупотребительный язык с ростом моделей программирования MapReduce .
Инъекция , уменьшение , свертывание , накопление и сжатие - это синонимы как класс функций свертывания . Я считаю согласованность всей вашей кодовой базы наиболее важной, но, поскольку различные сообщества предпочитают одно слово другому, тем не менее полезно знать альтернативы.
Чтобы подчеркнуть словосочетание «уменьшить карту», вот версия, которая немного более прощательна для того, что заканчивается в этом массиве.
Я согласен, reduceговорит мне больше о том, что делает функция, но injectзвучит намного круче.
everett1992
1
Согласитесь с последним комментарием, вы дали мне лучший ответ.
Jerska
1
Один комментарий , который я сделал бы то , что reduceи mapв функции высшего порядка предшествует MapReduce. Вдохновение идет другим путем. И в смысле MapReduce, это несколько иная операция, чем простое функциональное сокращение, которое влияет на взаимодействие разных машин.
Acjay
Кен Айверсон представил оператор / называемый «оператор сокращения» на языке программирования APL. Источник: Айверсон, Кеннет. 1962. Язык программирования. Wiley. Другой источник: «Нотация как инструмент мышления», лекция ACM Turing Award 1979 года, Кеннет Э. Айверсон, dl.acm.org/ft_gateway.cfm?id=1283935&type=pdf
Фернандо
112
В качестве альтернативы (просто для сравнения), если у вас установлен Rails (фактически только ActiveSupport):
Более новые версии activesupport на самом деле не загружают все расширения по умолчанию. Вы хотите , чтобы требовать либо только модуль суммы: require 'active_support/core_ext/enumerable.rb'или требовать все активной поддержки: require 'active_support/all'. Подробнее об этом здесь: API Docs
dcashman
2
Не важно , что activesupportэто массивное зависимость перетащить в проект , чтобы перейти от array.inject(:+)к array.sum.
meagar
1
Nitpick к хорошему комментарию: он должен быть require 'active_support/core_ext/enumerable'без .rbсуффикса, поскольку он добавлен неявно.
Пер Лундберг
72
Для Ruby> = 2.4.0 вы можете использовать sumиз Enumerables.
[1,2,3,4].sum
Опасно для базовых классов mokeypatch. Если вам нравится опасность и вы используете более старую версию Ruby, вы можете добавить #sumв Arrayкласс:
classArraydef sum
inject(0){|sum, x| sum + x }endend
Базовые классы обезьяноподготовки не очень приятны.
user3467349
1
Смысл его в том, что вам не нужно делать Monkey Patch для Ruby> = 2.4, и это исправление обезьяны опасно, и теперь вы можете суммировать перечислимые значения изначально, но есть и способ переназначить функциональность.
Питер Х. Болинг
Понижено, потому что ваша реализация возвращает ноль для пустых массивов.
Eldritch Conundrum
45
Новое для Ruby 2.4.0
Вы можете использовать метко названный метод Enumerable#sum. Он имеет много преимуществ по сравнению 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это так.
Ruby pre 2.4 - array.inject(:+)илиarray.reduce(:+)
* Примечание: этот #sumметод является новым дополнением для 2.4, enumerableтак что теперь вы сможете использовать его array.sumв чистом рубине, а не только в Rails.
Ruby 2.4.0 был выпущен сегодня с этой функцией! Am
амеба
@ amoebe вы правы! Рад видеть, что эта полезная функция включена.
собирать
19
Просто ради разнообразия вы можете сделать это, если ваш массив - это не массив чисел, а массив объектов, которые имеют свойства, которые являются числами (например, количество):
Это эквивалентно делать: array.map(&:amount).inject(0, :+). Смотрите другие ответы.
Ричард Джонс
4
В некотором смысле, да. Однако использование mapзатем injectтребует от вас циклически проходить по массиву дважды: один раз для создания нового массива, другой для суммирования членов. Этот метод немного более многословен, но и более эффективен.
# http://madeofcode.com/posts/74-ruby-core-extension-array-sumclassArraydef 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 }endendend
Это создаст строку «123 + 321 + 12389», а затем с помощью функции eval сделает сумму. Это только для целей игры в гольф , вы не должны использовать его в надлежащем коде.
[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.sum
Ответы:
Попробуй это:
Смотрите перечисляемую документацию Ruby
(примечание:
0
базовый случай необходим, чтобы0
вместо пустого массива он возвращалсяnil
)источник
array.inject(:+)
более эффективен.array.inject(:+)
кажется, вызывает проблемы в Ruby 1.8.6 Исключения «LocalJumpError: блок не указан» может появиться.array.sum
может дать вам сумму значений массива.reduce
псевдонимinject
(как вarray.reduce( :+ )
).inject
а неreduce
.Или попробуйте Ruby 1.9:
Примечание:
0
базовый регистр необходим, иначеnil
будет возвращен на пустых массивах:источник
array.map(&:price).inject(0, :+)
немного безопаснее Это гарантирует, что если у вас есть пустой список, вы получите 0, а не ноль .array.inject(0) { |sum, product| sum += product.price }
В то время как эквивалент
array.inject(0, :+)
, термин сокращение входит в более общеупотребительный язык с ростом моделей программирования MapReduce .Инъекция , уменьшение , свертывание , накопление и сжатие - это синонимы как класс функций свертывания . Я считаю согласованность всей вашей кодовой базы наиболее важной, но, поскольку различные сообщества предпочитают одно слово другому, тем не менее полезно знать альтернативы.
Чтобы подчеркнуть словосочетание «уменьшить карту», вот версия, которая немного более прощательна для того, что заканчивается в этом массиве.
Некоторые дополнительные соответствующие чтения:
источник
reduce
говорит мне больше о том, что делает функция, ноinject
звучит намного круче.reduce
иmap
в функции высшего порядка предшествует MapReduce. Вдохновение идет другим путем. И в смысле MapReduce, это несколько иная операция, чем простое функциональное сокращение, которое влияет на взаимодействие разных машин.В качестве альтернативы (просто для сравнения), если у вас установлен Rails (фактически только ActiveSupport):
источник
require 'active_support/core_ext/enumerable.rb'
или требовать все активной поддержки:require 'active_support/all'
. Подробнее об этом здесь: API Docsactivesupport
это массивное зависимость перетащить в проект , чтобы перейти отarray.inject(:+)
кarray.sum
.require 'active_support/core_ext/enumerable'
без.rb
суффикса, поскольку он добавлен неявно.Для Ruby> = 2.4.0 вы можете использовать
sum
из Enumerables.Опасно для базовых классов mokeypatch. Если вам нравится опасность и вы используете более старую версию Ruby, вы можете добавить
#sum
вArray
класс:источник
Новое для Ruby 2.4.0
Вы можете использовать метко названный метод
Enumerable#sum
. Он имеет много преимуществ по сравнениюinject(:+)
с некоторыми важными примечаниями, которые нужно прочитать в конце.Примеры
Изменяется
Массивы
Важная заметка
Этот метод не эквивалентен
#inject(:+)
. НапримерТакже,
Смотрите этот ответ для получения дополнительной информации о том, почему
sum
это так.источник
Ruby 2.4+ / Rails -
array.sum
т.е.[1, 2, 3].sum # => 6
Ruby pre 2.4 -
array.inject(:+)
илиarray.reduce(:+)
* Примечание: этот
#sum
метод является новым дополнением для 2.4,enumerable
так что теперь вы сможете использовать егоarray.sum
в чистом рубине, а не только в Rails.источник
Просто ради разнообразия вы можете сделать это, если ваш массив - это не массив чисел, а массив объектов, которые имеют свойства, которые являются числами (например, количество):
источник
array.map(&:amount).inject(0, :+)
. Смотрите другие ответы.map
затемinject
требует от вас циклически проходить по массиву дважды: один раз для создания нового массива, другой для суммирования членов. Этот метод немного более многословен, но и более эффективен.Рубин 1.8.7 следующим образом:
источник
Вы можете просто использовать:
источник
inject(:+)
а это нетinject :+
?Достаточно
[1,2,3].inject('+')
источник
Ruby 2.4.0 выпущен и имеет метод Enumerable # sum . Так что вы можете сделать
Примеры из документов:
источник
Также позволяет
[1,2].sum{|x| x * 2 } == 6
:источник
для массива с нулевыми значениями мы можем сделать компакт и затем ввести сумму
источник
Работает и для диапазонов ... следовательно,
источник
Если вы чувствуете гольф, вы можете сделать
Это создаст строку «123 + 321 + 12389», а затем с помощью функции eval сделает сумму. Это только для целей игры в гольф , вы не должны использовать его в надлежащем коде.
источник
Способ 1:
Способ 2:
Способ 3:
Способ 4: когда массив содержит нулевые и пустые значения, по умолчанию, если вы используете любые из вышеперечисленных функций, уменьшить, суммировать, внедрить все будет через
Вы можете преодолеть это,
Метод 6: Eval
Оценивает выражения Ruby в строке.
источник
3 способа сделать сумму массива
1)
array.inject(0){|sum,x| sum + x }
2)
array.inject('+')
3)
array.join('+')
источник
Или вы можете попробовать этот метод:
источник
Это самый короткий путь. Попробуй это.
array.inject :+
источник
* Это хорошо работает для меня, как нового разработчика. Вы можете настроить диапазон номеров, изменив значения в пределах []
источник
Вы также можете сделать это простым способом
источник
Вы можете использовать .map и .sum как:
источник
array.sum