Почему я должен использовать .inject (0), а не .inject для создания этой работы?

Я создаю приложение для направляющих и использовал этот код в одном из моих методов

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? Если так, почему это теперь работает? В противном случае затем, почему это не работает.

11
задан brad 22 March 2010 в 10:54
поделиться

2 ответа

Что мы можем прочитать в API:

Если вы явно не укажете начальное значение для memo, тогда будет использоваться {{ 1}} первый элемент коллекции используется как начальное значение памятки.

Итак, item_numbers [0] будет указано как начальное значение, но это не число, это объект. Итак, мы получили ошибку

undefined method `+ '.

Итак, мы должны указать начальное значение как 0

item_numbers.inject (0) {| sum, i | sum + i}

17
ответ дан 3 December 2019 в 04:31
поделиться

Это потому, что вы обращаетесь к 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 не вызывается на первом элементе, если начальное значение не передано явно.

7
ответ дан 3 December 2019 в 04:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: