11

我正在创建一个 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 吗?如果是这样,为什么它现在有效?如果没有,那为什么它不起作用。

4

3 回答 3

18

我们可以在 API 中读取的内容:

如果没有明确指定 memo 的初始值,则使用 collection 的第一个元素作为 memo 的初始值。

所以 item_numbers[0] 将被指定为一个初始值——但它不是一个数字,它是一个对象。所以我们有一个错误

未定义的方法“+”。

所以我们必须将初始值指定为 0

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

于 2010-03-22T11:58:01.803 回答
8

这是因为您正在访问i.amount而不仅仅是 plain 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当未显式传入起始值时,不会在第一个元素上调用。

于 2010-03-22T11:15:36.007 回答
0

有一天我也在用头撞它,所以我试着想象它。希望能帮助到你。在此处输入图像描述

于 2021-02-15T19:11:12.960 回答