0

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.

7
  • 1
    give us an example of this nested hash and the desired output Commented Dec 11, 2014 at 17:51
  • You haven't given us anything to work with. We need your minimal input sample, your expected output sample, and a minimal example of what you tried writing that demonstrates the problem you're seeing. Without that your question can be closed. Commented Dec 11, 2014 at 17:56
  • What information would providing a nested hash give you? The question was abundantly clear. Commented Dec 11, 2014 at 17:57
  • We know what a nested hash is. We don't know what the OP's input data looks like since it's deeply nested with arrays. We can imagine a lot of data formats that could meet that description and most would not have a bearing on the question, so it's up to the OP to provide something that narrows it down. Commented Dec 11, 2014 at 18:00
  • 2
    We can imagine a lot of data formats that could meet that description and most would not have a bearing on the question Why not? Commented Dec 11, 2014 at 18:02

1 Answer 1

1
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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.