MDT
MDT

Reputation: 1659

Hash of hashes, how to get keys of the first nested hash

I am using a hash of hashes in Ruby, called MYMOVIES, as below.

    {"127 Hours"=>
       {"title"=>"127 Hours",
       "year"=>"2010",
       "plays"=>1,
       "last_played"=>1300489200,
       "seen_date"=>"19/3/2011",
       "imdb_id"=>"tt1542344",
       "rating"=>"6",
       "omdbapiurl"=>"http://www.omdbapi.com/?t=127 Hours&y=2010"},
    "Zombieland"=>
       {"title"=>"Zombieland",
       "year"=>"2009",
       "plays"=>1,
       "last_played"=>1290207600,
       "seen_date"=>"20/11/2010",
       "imdb_id"=>"tt1156398",
       "rating"=>"7",
       "omdbapiurl"=>"http://www.omdbapi.com/?t=Zombieland&y=2009"}}

Now, I would like to get all the keys of the first nested hash (i.e. title, year, plays, ..., omdbapiurl).

I tried with:

   mynestedhash = MYMOVIES.first
   puts mynestedhash.keys.to_s

But I get the error:

    undefined method `keys' for #<Array:0x801c56f8> (NoMethodError)

How could I do?

Upvotes: 0

Views: 688

Answers (3)

ovhaag
ovhaag

Reputation: 1278

If all inner hashes have the same keys, the following will suffice

first_outer_key, first_outer_value = MYMOVIES.first 
first_inner_hash = first_outer_value # change name to show what we have
inner_keys = first_inner_hash.keys

If the keys of the inner hashes can be different, you should join them like Priti and toro2k did in their solutions.

Upvotes: 2

toro2k
toro2k

Reputation: 19230

This should do:

MYMOVIES.map { |_, h| h.keys }.flatten.uniq
# => ["title", "year", "plays", "last_played", "seen_date", "imdb_id", "rating", "omdbapiurl"] 

Your code didn't work because the method first returns an array, not a hash:

MYMOVIES.first
# => ["127 Hours", {"title"=>"127 Hours", ... }]]

Update If you want to get the keys of the first hash, then you could do:

nested_hash = MYMOVIES.first[1]
nested_hash.keys
# => ["title", "year", "plays", "last_played", "seen_date", "imdb_id", "rating", "omdbapiurl"] 

Or alternatively:

_, nested_hash = MYMOVIES.first
nested_hash.keys
# => ["title", "year", "plays", "last_played", "seen_date", "imdb_id", "rating", "omdbapiurl"] 

Upvotes: 2

Arup Rakshit
Arup Rakshit

Reputation: 118261

require 'pp'
h = {"127 Hours"=>
       {"title"=>"127 Hours",
       "year"=>"2010",
       "plays"=>1,
       "last_played"=>1300489200,
       "seen_date"=>"19/3/2011",
       "imdb_id"=>"tt1542344",
       "rating"=>"6",
       "omdbapiurl"=>"http://www.omdbapi.com/?t=127 Hours&y=2010"},
    "Zombieland"=>
       {"title"=>"Zombieland",
       "year"=>"2009",
       "plays"=>1,
       "last_played"=>1290207600,
       "seen_date"=>"20/11/2010",
       "imdb_id"=>"tt1156398",
       "rating"=>"7",
       "omdbapiurl"=>"http://www.omdbapi.com/?t=Zombieland&y=2009"}}

pp h.flat_map{|k,v| v.keys}.uniq

Output

["title",
 "year",
 "plays",
 "last_played",
 "seen_date",
 "imdb_id",
 "rating",
 "omdbapiurl"]

Now see why your code didn't work below :

h = {"127 Hours"=>
       {"title"=>"127 Hours",
       "year"=>"2010",
       "plays"=>1,
       "last_played"=>1300489200,
       "seen_date"=>"19/3/2011",
       "imdb_id"=>"tt1542344",
       "rating"=>"6",
       "omdbapiurl"=>"http://www.omdbapi.com/?t=127 Hours&y=2010"},
    "Zombieland"=>
       {"title"=>"Zombieland",
       "year"=>"2009",
       "plays"=>1,
       "last_played"=>1290207600,
       "seen_date"=>"20/11/2010",
       "imdb_id"=>"tt1156398",
       "rating"=>"7",
       "omdbapiurl"=>"http://www.omdbapi.com/?t=Zombieland&y=2009"}}

h.first
#["127 Hours",
# {"title"=>"127 Hours",
# "year"=>"2010",
# "plays"=>1,
# "last_played"=>1300489200,
# "seen_date"=>"19/3/2011",
# "imdb_id"=>"tt1542344",
# "rating"=>"6",
# "omdbapiurl"=>"http://www.omdbapi.com/?t=127 Hours&y=2010"}]
p h.first.grep /keys/
#[]

Now it is clear that from #grep method that Array don't have keys method. So try the above code to make it workable.

Upvotes: 1

Related Questions