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

Popular posts from this blog

sql - VB.NET Operand type clash: date is incompatible with int error -

SVG stroke-linecap doesn't work for circles in Firefox? -

python - TypeError: Scalar value for argument 'color' is not numeric in openCV -