我正在创建一个rails应用程序,并在我的一个方法中使用了此代码
item_numbers.inject(0) {|sum, i| sum + i.amount}
item_numbers是我的item_numbers表中的一个对象数组。我应用于它们的.amount方法在一个单独的表中查找item_number的值,并将其作为BigDecimal对象返回。显然,inject方法然后添加了所有返回的i.amount对象,这很好用。
我只是好奇为什么当我把这句话写成
时它不起作用item_numbers.inject {|sum, i| sum + i.amount}
根据我信赖的镐书,这些应该是等价的。是因为i.amount是BigDecimal吗?如果是这样,为什么它现在有用?如果没有,那么为什么它不起作用。
答案 0 :(得分:16)
我们在API中可以阅读的内容:
如果您没有明确指定 备忘录的初始值,然后使用 集合的第一个元素用作 备忘录的初始值。
因此item_numbers [0]将被指定为初始值 - 但它不是数字,而是一个对象。所以我们得到了一个错误
未定义的方法`+'。
所以我们必须将初始值指定为0
item_numbers.inject(0){| sum,i |总和+ i}
答案 1 :(得分:7)
这是因为您正在访问i.amount
而不是普通的i
。在不起作用的版本中,您隐式执行item_numbers[0] + item_numbers[1].amount + ...
。
一个简写是item_numbers.map(&:amount).inject(&:+)
,但如果map
没有返回枚举器,那么这种方式会导致列表上的两次迭代。
如果这没有说服你,如果我们在Fixnum上定义一个方法amount
,在返回它之前打印该值,请查看打印出来的内容:
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
。
答案 2 :(得分:0)