简体   繁体   中英

access hashes of hashes values in ruby

I have a nested hashes in ruby and I need to access a specific value of it. My hash look like below.

hash = 

    {"list"=>
      {"0"=>
        {"date"=>"11/03/2014",
         "item1"=>"",
         "tiem2"=>"News",
         "item3"=>"",
         "item4"=>"",
         "item5"=>"Videos",
         "Type"=>"Clip"},
       "1"=>
         {"date"=>"11/03/2014",
         "item1"=>"",
         "tiem2"=>"News",
         "item3"=>"",
         "item4"=>"",
         "item5"=>"Videos",
         "Type"=>"Program"}
    }}

I need to access the value of "Type" of each keys. I tried with the below code but I am not sure why it didn't work.

hash_type = hash["list"].keys.each {|key| puts key["Type"]}

But it returned the list of keys. ie 0 and 1

Please help.

hash["list"].map {|_, hash| hash['Type']}

Explanation:

hash = {key: 'value'}

You can loop over a hash using each like this:

hash.each {|pair| puts pair.inspect }    #=> [:key, 'value']

or like this

hash.each {|key, value| puts "#{key}: #{value}"} #=> key: value

Since we don't use key anywhere, some of the IDEs will complain about unused local variable key . To prevent this it is ruby convention to use _ for variable name and all the IDEs will not care for it to be unused.

hash['list'].collect { |_, value| value['Type'] }
 => ["Clip", "Program"]

This is following your logic (some answers posted different ways to do this). The reason why you go things wrong, if we go step by step is:

hash_type = hash["list"].keys #=> ["0", "1"]

So everything after that is the same like:

["0", "1"].each {|key| puts key["Type"]}

So you're basically doing puts '1'['Type'] and '0'['Type'] which both evaluate to nil (try it in IRB) . Try replacing the puts with p and you'll get nil printed 2 times. The reason why you're getting hash_type to be ["0", "1"] is because your last expression is keys.each and each ALWAYS return the "receiver", that is the array on which you called each (as we saw earlier, that array is ["0", "1"]).

The key to solving this, following your particular logic, is to put the "keys" (which are '0' and '1' in this instance) in the appropriate context , and putting them in a context would look something like this:

hash_type = hash["list"].keys.each {|key| puts hash["list"][key]["Type"]}` 

This will print the keys. However, hash_type will still be ["0", "1"] (remember, each returns the value of the receiver). If you want the actual type values to be stored in hash_types, replace each with map and remove puts :

hash_type = hash["list"].keys.map {|key|  hash["list"][key]["Type"]} #=> ["Clip", "Program"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM