Axil
Axil

Reputation: 3311

How to simplify hash intersection with array

I have hash data (originally in json) and an array of selected hash keys:

jsondata ='{"1":
          {"name": "Tax Exempt"},
       "2":
          {"name": "Tax on Purchases"},
       "3":
          {"name": "Tax on Sales"},
       "4":
          {"name": "Service Tax"}              
        }'
parseddata = JSON.parse(jsondata);    
selectedtax = ["2","3"]

My code maps the keys and returns the value of the hash that exist in the array. Here is the code:

selectedtaxdetails = Array.new
parseddata.map do |key,value|  
  if selectedtax.include? key 
    selectedtaxdetails << value               
  end
end  

Output of selectedtaxdetails is:

[{"name": "Tax on Purchases"},{"name": "Tax on Sales"}] 

How can I improve my code?

Upvotes: 0

Views: 385

Answers (2)

BroiSatse
BroiSatse

Reputation: 44715

Solution:

You can do (rails):

parseddata.slice(*selectedtax).values

or even simpler (pure ruby):

parseddata.values_at(*selectedtax)

Explanation:

Both slice and values_at methods expect a list of keys. If you just pass an array it will search for values where this array is a key, whcih obviously is not what you want. Instead you can use a splat operator (*). It will take each element of an array and will pass it into a method as a separate argument, which is exactely what we want here.

Update:

To achieve structure: [{"code":"2", "name": "Tax on Purchase"},{"code":"3", "name": "Tax on Sales"}] you can do (rails):

parseddata.slice(*selectedtax).map {|key, value| value.dup.tap {|h| h['code'] = key}}

or with pure ruby:

parseddata.select{|key,_| selectedtax.include? key}.map {|key, value| value.dup.tap {|h| h['code'] = key}}

Upvotes: 4

Gustavo Cha&#237;n
Gustavo Cha&#237;n

Reputation: 943

The following should do the same in one line

parseddaata.values_at(*selectedtax)

Upvotes: 0

Related Questions