ruby-on-rails - 如何在不预先定义哈希/对象的情况下增加它们的值

标签 ruby-on-rails ruby

我正在做 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/

相关文章:

mysql - 多态性| self 引用| Rails 事件记录模型

javascript - 在 application.css 中找不到//=require jquery.nouislider

ruby - 如何在 Ruby 上引用这个?

regex - 如何使用 Regexp.union 构建不区分大小写的正则表达式

ruby-on-rails - rails : Turn off error display

ruby-on-rails - 我怎样才能以 ruby 开始当前的工作日?

ruby-on-rails - 如何处理 Rails 中的散列嵌套键验​​证?

ruby-on-rails - 目录 : Polymorphic Controllers

ruby-on-rails - 如何修复低于 "but your Gemfile requires activesupport 3.0.0"的错误

ruby-on-rails - NameError:未初始化的常量 Minitest::VERSION