kchromik
kchromik

Reputation: 1388

Get all keys from ruby hash also where value is array with hashes

If I have a Hash such as with subhashes, which are nested in arrays of the value of a Hash:

{"school" => "School name", "teachers" => [{"name" => "Schmith", "age" => 34},{"name" => "McRight", "age" => 51}]}


def get_keys(hash)
    (hash.keys + hash.values.grep(Hash){|sub_hash| get_keys(sub_hash)}).flatten
end

With the previous function I can get only ["school","teachers"], but I need also the keys of the hashes, which are in the array of the "teachers" value: ["school","teachers","name","age","name","age"]

Preferable I would like to eliminate duplications in the result to have: ["school","teachers","name","age"]

Upvotes: 0

Views: 1743

Answers (2)

Anthony
Anthony

Reputation: 15987

You can use Enumerable#each_with_object to do something like this and when the value is an Array, call the same function recursively for each object in the array.

hash = {"school" => "School name", "teachers" => [{"name" => "Schmith", "age" => 34},{"name" => "McRight", "age" => 51}]}

def get_keys(hash)
  hash.each_with_object([]) do |(k, v), arr|
    arr << k
    if v.is_a? Array
      arr << v.map { |hash2| get_keys(hash2) }.uniq
    end
  end
end

puts get_keys(hash)
=> ["school", "teachers", "name", "age"]

Upvotes: 2

dgmora
dgmora

Reputation: 1267

def get_keys(object)
  if object.is_a? Hash
    (object.keys + get_keys(object.values)).flatten.uniq
  elsif object.is_a? Array 
    object.collect{|value| get_keys value}
  else
    []
  end
end

I think this is quite clear, and you can nest as much as you want. If the object is not an array or hash, then there are no keys. If it's an array, it will look for the keys that could be in all the elements And if it's a hash, it will return its keys, plus the keys of the hashes that could be on the values of the hash. Then you apply flatten to remove possible empty arrays, and uniq to remove duplicate values.

With arrays, it will get the keys that could be inside of the

Upvotes: 2

Related Questions