我正在做 Rails 项目
我有一个产品哈希值,它们的唯一代码作为键
products = [
{"dt": "2016-01-01",
"quantity": 122,
"amount": 123000
},
{"dt": "2016-01-02",
"quantity": 97,
"amount": 97800
}
{"dt": "2016-01-03",
"quantity": 142,
"amount": 163000
}
]
我的目标是创建这 3 天报告的数量总和。我遍历对象。我想为名为“total_quantity”的数组中的每个对象添加新属性,该属性在每次迭代中都会增加。
products.each do |row|
rowqty += row['quantity']
rowamount += row['amount']
row['total_quantity'] = rowqty
row['total_amount'] = rowamount
end
您可以看到我定义了两个额外的变量“rowqty”和“rowamount”来保存更新后的数据,然后再使用它们来创建每个对象的新属性。
但是我得到了这个错误
undefined method `+' for nil:NilClass
但是,如果我在迭代之前预先定义变量,它似乎可以工作。像这样
rowqty = 0
rowamount = 0
products.each do |row|
rowqty += row['quantity']
rowamount += row['amount']
row['total_quantity'] = rowqty
row['total_amount'] = rowamount
end
我知道它需要变量存在才能对其进行处理。但我不得不承认,我知道当数据变得更加复杂时,我会遇到这样的问题。
那么有没有办法对不存在于范围内的变量应用数学运算,如增加、减少或其他任何东西?
在 PHP 中,似乎是在该点创建新变量。这包括数组和对象。但我不能在 Rails 中做到这一点
最佳答案
在 PHP 中, undefined variable 将默认为 0
并在您首次尝试向其添加内容时为您实例化。
$unknown_var += 1; // This works!
在 Ruby 中,如果你尝试做同样的事情,你会得到一个错误,所以你必须在递增它之前定义你的变量:
known_var = 0
known_var += 1 # This works, but not if you don't define your variable first
在回答您的问题时,您只需在使用变量之前定义变量。至关重要的是,您必须在循环内生成的范围之外定义变量,否则每次循环运行时变量都会重置,并且您将无法按照您的方式在数组中执行总和计算是。
问题中的最后一个示例是正确的方法,无需使用更复杂的东西,如 inject
。
根据 Sema 的回答,使用注入(inject)你可以实现相同的求和,但不要忘记也修改你的初始数据集:
products.inject([0, 0]) do |data, product|
data[0] += product['quantity']
data[1] += product['amount']
product['total_quantity'] = data[0]
product['total_amount'] = data[1]
data
end
但是,这仍然会在您调用 inject
时定义一个局部变量,并且会在数组的每次迭代中递增其中的值。
顺便说一句,测试这两个选项的速度表明您的原始解决方案是最快的:
Calculating -------------------------------------
Using Array#each 36.667k i/100ms
Using Array#inject 31.819k i/100ms
-------------------------------------------------
Using Array#each 427.696k (± 7.8%) i/s - 2.127M
Using Array#inject 362.753k (± 4.2%) i/s - 1.814M
Comparison:
Using Array#each: 427695.7 i/s
Using Array#inject: 362753.2 i/s - 1.18x slower
用于生成此基准的代码:https://gist.github.com/pacso/f7e997593bd15bd121d1
关于ruby-on-rails - 如何在不预先定义哈希/对象的情况下增加它们的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34917523/