Reputation: 1328
I'm am getting a nested hash from Facebook. It has arrays inside which have more hashes and vice versa.
Now I am trying to find every occurence of a hash that is deeply nested.
In my case I am searching for every value that has the key "tags" and then push it into an array.
I have found a solution for a unique key in "Find key/value pairs deep inside a hash containing an arbitrary number of nested hashes and arrays".
How can I do the same thing when the key is not unique and push every result into an array?
Edit:
Here is an example response I am getting from the facebook graph api.
{"albums"=>{"data"=>[{"id"=>"1406826642942218",
"created_time"=>"2014-12-11T10:54:13+0000",
"photos"=>{"data"=>[{"created_time"=>"2014-12-11T10:54:13+0000",
"id"=>"1406826626275553"}],
"paging"=>{"cursors"=>{"before"=>"MTQwNjgyNjYyNjI3NTU1Mw==", "after"=>"MTQwNjgyNjYyNjI3NTU1Mw=="}}}},
{"id"=>"1406825849608964",
"created_time"=>"2014-12-11T10:52:34+0000",
"photos"=>{"data"=>[{"created_time"=>"2014-12-11T10:52:34+0000",
"id"=>"1406825782942304"}],
"paging"=>{"cursors"=>{"before"=>"MTQwNjgyNTc4Mjk0MjMwNA==", "after"=>"MTQwNjgyNTc4Mjk0MjMwNA=="}}}},
{"id"=>"1405097859781763",
"created_time"=>"2014-12-08T14:50:51+0000"
, "photos"=>{"data"=>[{"created_time"=>"2014-12-08T14:51:12+0000", "id"=>"1405097983115084"}],
"paging"=>{"cursors"=>{"before"=>"MTQwNTA5Nzk4MzExNTA4NA==", "after"=>"MTQwNTA5Nzk4MzExNTA4NA=="}}}},
{"id"=>"1392256877732528",
"created_time"=>"2014-11-17T14:37:00+0000",
"photos"=>{"data"=>[{"created_time"=>"2014-12-08T14:24:41+0000",
"id"=>"1405084986449717"},
{"tags"=>{"data"=>[{"id"=>"100007516267052",
"name"=>"Dorothy Amgeafbfgjeb Qinman",
"created_time"=>"2014-11-17T14:37:12+0000",
"x"=>46.604215456674, "y"=>72.330827067669},
{"id"=>"100007456544855",
"name"=>"Richard Amgdefeddhee Carrierosen",
"created_time"=>"2014-11-17T14:37:11+0000",
"x"=>45.433255269321, "y"=>48.571428571429},
{"id"=>"100008446877693",
"name"=>"Karen Amhddfhggfic Chaison",
"created_time"=>"2014-11-17T14:37:09+0000",
"x"=>49.414519906323, "y"=>31.578947368421}],
"paging"=>{"cursors"=>{"before"=>"MTAwMDA3NTE2MjY3MDUy", "after"=>"MTAwMDA4NDQ2ODc3Njkz"}}},
"created_time"=>"2014-11-17T14:37:01+0000",
"id"=>"1392256757732540"}],
"paging"=>{"cursors"=>{"before"=>"MTQwNTA4NDk4NjQ0OTcxNw==", "after"=>"MTM5MjI1Njc1NzczMjU0MA=="}}}}],
"paging"=>{"cursors"=>{"after"=>"MTM5MjI1Njg3NzczMjUyOA==", "before"=>"MTQwNjgyNjY0Mjk0MjIxOA=="}}},
"id"=>"100008446877693"}
What I want to get is this part
{"tags"=>{"data"=>[{"id"=>"100007516267052",
"name"=>"Dorothy Amgeafbfgjeb Qinman",
"created_time"=>"2014-11-17T14:37:12+0000",
"x"=>46.604215456674, "y"=>72.330827067669},
{"id"=>"100007456544855",
"name"=>"Richard Amgdefeddhee Carrierosen",
"created_time"=>"2014-11-17T14:37:11+0000",
"x"=>45.433255269321, "y"=>48.571428571429},
{"id"=>"100008446877693",
"name"=>"Karen Amhddfhggfic Chaison",
"created_time"=>"2014-11-17T14:37:09+0000",
"x"=>49.414519906323, "y"=>31.578947368421}],
Which could be at multiple places depending on how many pictures have tags on them.
I hope this makes it more clear.
Upvotes: 0
Views: 1070
Reputation: 1642
def nested_hash_values(obj,key)
r = []
if obj.is_a?(Hash)
r.push(obj[key]) if obj.key?(key)
obj.each_value { |e| r += nested_hash_values(e,key) }
end
if obj.is_a?(Array)
obj.each { |e| r += nested_hash_values(e,key) }
end
r
end
a = {"foo"=>["bar", "x", {"bar"=>["hello", {"foo"=>"world"}, "world!"], "foo"=>"BAR!"}, "enough?"], "bar"=>"foo"}
nested_hash_values(a, "foo")
=> [["bar", "x", {"bar"=>["hello", {"foo"=>"world"}, "world!"], "foo"=>"BAR!"}, "enough?"], "BAR!", "world"]
should return an array with all values found for a given key.
You could add additional if e.is_a?(Array) || e.is_a?(Hash)
in the each blocks. This would avoid unnecessary method calls and speed the function up a little, but add additional code.
Upvotes: 1