need help in getting nested ruby hash hierarchy

2019-04-10 19:29发布

问题:

I have hash deep nested hash and i want the hierarchy(parent to child) for each key as an array.

for example -

 hash = {
"properties"=>{
    "one"=>"extra",
    "headers"=>{
        "type"=>"object",
        "type1"=>"object2"
    },
    "entity"=>{
        "type"=>"entype"
    },       
},
"sec_prop"=>"hmmm"
}

for this hash I want output as given below, as a separate array for each key.

[properties,one]
[properties,headers,type]
[properties,headers,type1]
[properties,entity,type]
[sec_prop]

i have been trying and searching this for so long through some recursive methods but it doesn't seems to work for me any help will be appreciated.

important thing to notice here is there are duplicate keys in the same hash as a nesting for example type key is repeated in both headers and entity. so that i need proper hierarchy to identify the proper key

and i should get this array of hierarchy only for those keys whose value is not a another hash.

It should be in the format above given but any other solutions also welcome

thanks.!

回答1:

Here is my try :

hash = {
  "properties"=>{
    "one"=>"extra",
    "headers"=>{
      "type"=>"object",
      "type1"=>"object2"
    },
    "entity"=>{
      "type"=>"entype"
    },       
  },
  "sec_prop"=>"hmmm"
}

def fetch_keys(h)
  h.flat_map do |k,v|
    if v.is_a?(Hash)
      fetch_keys(v).map do |keys|
        [k] + Array(keys)
      end
    else
      k
    end
  end
end

fetch_keys(hash)
# => [["properties", "one"],
#     ["properties", "headers", "type"],
#     ["properties", "headers", "type1"],
#     ["properties", "entity", "type"],
#     "sec_prop"]


回答2:

Recursion to the rescue:

def hashkeys(o, keys = [], result = [])
  if o.is_a?(Hash)
    o.each do |key, value|
      hashkeys(value, keys + [key], result)
    end
  else
    result << keys
  end
  result
end

This is a depth first search which accumulates keys until it gets to a leaf (a non-Hash value). Each time it get to a leaf, it adds the accumulated keys to the result.

pp hashkeys(hash)
# => [["properties", "one"],
# =>  ["properties", "headers", "type"],
# =>  ["properties", "headers", "type1"],
# =>  ["properties", "entity", "type"],
# =>  ["sec_prop"]]


标签: ruby arrays hash