Я создаю приложение для направляющих и использовал этот код в одном из моих методов
item_numbers.inject(0) {|sum, i| sum + i.amount}
item_numbers является массивом объектов от моей item_numbers таблицы. .amount метод, что я обращаюсь к ним, ищет значение item_number в отдельной таблице и возвращает его, поскольку BigDecimal возражает. Очевидно, вводить метод затем добавляет все возвращенные объекты i.amount, и это работает просто великолепно.
Мне просто любопытно относительно того, почему это не работало, когда я записал этот оператор как
item_numbers.inject {|sum, i| sum + i.amount}
Согласно моей испытанной книге кирки они должны быть эквивалентными. Это, потому что i.amount является BigDecimal? Если так, почему это теперь работает? В противном случае затем, почему это не работает.
Что мы можем прочитать в API:
Если вы явно не укажете начальное значение для memo, тогда будет использоваться {{ 1}} первый элемент коллекции используется как начальное значение памятки.
Итак, item_numbers [0] будет указано как начальное значение, но это не число, это объект. Итак, мы получили ошибку
undefined method `+ '.
Итак, мы должны указать начальное значение как 0
item_numbers.inject (0) {| sum, i | sum + i}
Это потому, что вы обращаетесь к i.amount
, а не просто к i
. В версии, которая не работает, вы неявно выполняете item_numbers[0] + item_numbers[1].amount + ...
.
Одним из сокращений может быть item_numbers.map(&:amount).inject(&:+)
, но этот способ может привести к двум итерациям над списком, если map
не возвращает перечислитель.
Если это вас не убедило, посмотрите, что будет выведено, если мы определим метод amount
на Fixnum, который выводит значение перед возвратом:
irb(main):002:1> def amount
irb(main):003:2> puts "My amount is: #{self}"
irb(main):004:2> return self
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> [1,2,3].inject { |sum, i| sum + i.amount }
My amount is: 2
My amount is: 3
=> 6
irb(main):008:0> [1,2,3].inject(0) { |sum, i| sum + i.amount }
My amount is: 1
My amount is: 2
My amount is: 3
=> 6
irb(main):009:0>
Мы видим, что amount
не вызывается на первом элементе, если начальное значение не передано явно.