ruby one liners to create hash

August 20, 2009 by · 1 Comment
Filed under: technology 

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.

  • Recent Posts