Denis
Denis

Reputation: 222

Rails hash tree to array

I'm trying to parse a large XML file. I'm using Saxerator.

My hash has a kind of tree:

obj= {
  "id"=>'1', "groups" =>{
  "group" =>[
   {"id"=>"2", "groups"=>{}},
   {"id"=>"3", "groups"=>{}},
   {"id"=>"4", "groups"=>{
     "group"=>[
       {"id"=>"5", "groups"=>{}},
       {"id"=>"6", "groups"=>{}},
     ]}}
]}}

I don't know in advance the depth of the tree. I had a problem. I have no idea how convert it in array. Result should be like this:

[{"id"=> "1", "parent_id"=> "0"},
{"id"=> "2", "parent_id"=> "1"},
{"id"=> "3", "parent_id"=> "1"},
{"id"=> "4", "parent_id"=> "1"},
{"id"=> "5", "parent_id"=> "4"},
{"id"=> "6", "parent_id"=> "4"}]

Have any ideas?

Upvotes: 1

Views: 756

Answers (2)

amnn
amnn

Reputation: 3716

You're looking for a very simple recursive function, which linearises the tree but also keeps track of the parent:

def tree_to_a(tree, p = 0)
  id = tree["id"]
  (tree["groups"]["group"] || [])
    .flat_map { |sub| tree_to_a(sub, id) }
    .unshift("id" => id, "parent_id" => p)
end

Upvotes: 5

Sanket
Sanket

Reputation: 490

I have modified your object I hope its correct.

obj= {
  "id"=>'1', "groups" =>{
  "group" =>[
   {"id"=>"2", "groups"=>{}},
   {"id"=>"3", "groups"=>{}},
   {"id"=>"4", "groups"=>{
     "group"=>[
       {"id"=>"5", "groups"=>{}},
       {"id"=>"6", "groups"=>{}},
     ]}}
]}}

Then this your solution.

result = []
def create_hash(result, obj, id)
  result << {id: obj['id'], parent_id: id}
  if obj['groups']['group']
    obj['groups']['group'].each do |g|
      create_hash(result, g, obj['id'])
    end
  end
end
create_hash(result, obj, 0)
result // [{:id=>"1", :parent_id=>0}, {:id=>"2", :parent_id=>"1"}, {:id=>"3", :parent_id=>"1"}, {:id=>"4", :parent_id=>"1"}, {:id=>"5", :parent_id=>"4"}, {:id=>"6", :parent_id=>"4"}]

Upvotes: 1

Related Questions