ruby on rails - How to increment the value in Hash/Object without pre-defining them -
i working on rails project
i have hash of products unique codes keys
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 } ]
my objective create sum of quantity of these 3 days report. iterate through object. want add new attribute each of object inside array named "total_quantity" increased in each iteration.
products.each |row| rowqty += row['quantity'] rowamount += row['amount'] row['total_quantity'] = rowqty row['total_amount'] = rowamount end
you can see define 2 additional variables "rowqty" , "rowamount" hold updated data before using them create new attributes of each object.
but error
undefined method `+' nil:nilclass
however, if pre-define variables before iteration, seems work. this
rowqty = 0 rowamount = 0 products.each |row| rowqty += row['quantity'] rowamount += row['amount'] row['total_quantity'] = rowqty row['total_amount'] = rowamount end
i understand requires variable existence in order it. have confess can see encounter such problem when data becomes more complicated.
so there anyway apply mathematical operations increase, decrease or whatever variables not exit in scope?
in php, seems create new variable @ point. includes arrays , objects. can not in rails
in php, undefined variable default 0
, instantiated when first try add it.
$unknown_var += 1; // works!
in ruby error if try same thing, must define variable before can increment it:
known_var = 0 known_var += 1 # works, not if don't define variable first
in answer question, need define variables before can use them. critically, must define variable outside of scope generated within loop, otherwise variable reset each time loop runs , not able perform sum calculation across array way are.
your final example in question correct way without using more complicated inject
.
as per sema's answer, using inject implement same summing, don't forget modify initial dataset:
products.inject([0, 0]) |data, product| data[0] += product['quantity'] data[1] += product['amount'] product['total_quantity'] = data[0] product['total_amount'] = data[1] data end
however, still define local variable when call inject
, increment values within upon each iteration of array.
incidentally, testing speed of these 2 options shows original solution fastest:
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
code used generate benchmark: https://gist.github.com/pacso/f7e997593bd15bd121d1
Comments
Post a Comment