ruby one liners to create hash
Yesterday while going through one of my old programs, I found this written by me sometime back :
#begin magic
hash=Hash[*CGI.unescape(raw_text).split('&').map{|x| b=x.split("=");b.push(nil) if b.size==1;b}.flatten]
#end magic
To kill some of suspense let me disclose that raw_text looks like
"SUCCESS&mc_gross=10.00&protection_eligibility=Ineligible&payer_id=U7PPJJ4TSJ47E&tax=0.00&payment_date=09%3A45%3A30+Jul+10%2C+2009+PDT&payment_status=Pending"
, right it has been cut from paypal payment acknowledgment.
Above line if broken in parts reads better :
unescaped_array= CGI.unescape(raw_text).split('&')
unescaped_array= unescaped_array.collect{|x| b=x.split("=");b.push(nil) if b.size==1;b}
flattened_array= unescaped_array.flatten
hash= Hash[*flattened_array]
Let’s do individual steps in irb:
irb(main):009:0>unescaped_array= CGI.unescape(raw_text).split('&')
=> ["SUCCESS", "mc_gross=10.00", "protection_eligibility=Ineligible", "payer_id=U7PPJJ4TSJ47E", "tax=0.00", "payment_date=09:45:30 Jul 10, 2009 PDT", "payment_status=Pending"]
irb(main):013:0> unescaped_array= unescaped_array.map{|x| b=x.split("=");b.push(nil) if b.size==1;b}
=> [["SUCCESS", nil], ["mc_gross", "10.00"],["protection_eligibility", "Ineligible"], ["payer_id", "U7PPJJ4TSJ47E"], ["tax", "0.00"], ["payment_date", "09:45:30 Jul 10, 2009 PDT"], ["payment_status", "Pending"]]
irb(main):014:0> flattened_array= unescaped_array.flatten
=> ["SUCCESS", nil, "mc_gross", "10.00", "protection_eligibility", "Ineligible", "payer_id", "U7PPJJ4TSJ47E", "tax", "0.00", "payment_date", "09:45:30 Jul 10, 2009 PDT", "payment_status", "Pending"]
irb(main):015:0>
hash= Hash[*flattened_array]
=> {"tax"=>"0.00", "payment_status"=>"Pending", "payer_id"=>"U7PPJJ4TSJ47E", "mc_gross"=>"10.00", "SUCCESS"=>nil, "payment_date"=>"09:45:30 Jul 10, 2009 PDT", "protection_eligibility"=>"Ineligible"}
BTW, * is called splat operator in ruby
Another way to create hash from ‘array of pairs ‘ is to use inject :
hash= [[1,2],[3,4]].inject({}){|result,element| result[element.first]= result[element.last]; result}
There is one more way
Write a loop, that I’ll leave as an exercise to the readers !!
Here is a bit unrelated use case of creating hash from arrays:
irb(main):005:0> [1,2,3,4,7,9].group_by{|x| x<5 ? :lesser : :greater}
=> {:lesser=>[1, 2, 3, 4], :greater=>[7, 9]}
You can do more things, basically result of the block is used as the key for that element in the resulting hash.



































