为什么我需要使用 .inject(0) 而不是 .inject 来完成这项工作?
我正在创建一个 Rails 应用程序,并在我的方法之一中使用了此代码
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 吗?如果是这样,为什么它现在起作用了?如果没有,那么为什么它不起作用。
I am creating a rails app and have used this code in one of my methods
item_numbers.inject(0) {|sum, i| sum + i.amount}
item_numbers is an array of objects from my item_numbers table. The .amount method that I apply to them looks up the value of an item_number in a separate table and returns it as a BigDecimal object. Obviously the inject method then adds all of the returned i.amount objects and this works just fine.
I am just curious as to why it didn't work when I wrote this statement as
item_numbers.inject {|sum, i| sum + i.amount}
According to my trusty pickaxe book these should be equivalent. Is it because i.amount is a BigDecimal? If so, why does it now work? If not, then why doesn't it work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我们可以从 API 中读取到:
因此 item_numbers[0] 将被指定为初始值 - 但它不是一个数字,它是一个对象。所以我们有一个错误
所以我们必须将初始值指定为0
What we can read in API:
So item_numbers[0] will be specified as an initial value - but it is not a number, it is an object. So we have got an error
So we have to specify initial value as 0
这是因为您正在访问
i.amount
而不是简单的i
。在不起作用的版本中,您隐式执行item_numbers[0] + item_numbers[1].amount + ...
。一种简写是
item_numbers.map(&:amount).inject(&:+)
,但如果map
的话,这种方式可能会导致对列表进行两次迭代不返回枚举器。如果这不能说服您,请看看如果我们在 Fixnum 上定义一个在返回值之前打印该值的方法
amount
会打印出什么:我们可以清楚地看到
amount
当未显式传入起始值时,不会在第一个元素上调用。It's because you are accessing
i.amount
as opposed to just plaini
. In the version that doesn't work, you're implicitly doingitem_numbers[0] + item_numbers[1].amount + ...
.One shorthand would be
item_numbers.map(&:amount).inject(&:+)
, but that way can result in two iterations over the list, ifmap
doesn't return an enumerator.If that didn't convince you, look at what gets printed out if we define a method
amount
on Fixnum that prints the value before returning it:We can see clearly that
amount
is not called on the first element when a starting value is not explicitly passed in.有一天我也用头撞它,所以我试着想象它。希望它有帮助。
I was also banging my head against it some day, so I tried to visualize it. Hope it helps.