Reputation: 9467
Given a hash tree like this:
hash_tree = {
<Category id: 1, title: "foo"> => {},
<Category id: 2, title: "bar"> => {
<Category id: 3 title: "baz"> => {
<Category id: 4 title: "qux"> => {}
}
},
<Category id: 5, title: "norf"> => {}
}
I would like an elegant way of creating a flat array of hashes, with order preserved, with the depth added to each hash as a key, eg:
flat_array = [
{ value: 1, text: "foo", depth: 0 },
{ value: 2, text: "bar", depth: 0 },
{ value: 3, text: "baz", depth: 1 },
{ value: 4, text: "quz", depth: 2 },
{ value: 5, text: "norf", depth: 0 }
]
Each of the objects that make up the hash tree are quite a bit more complex than in the example above with more attributes, but all I need in my array is the ID and title - but note that the keys have changed.
Thanks
Upvotes: 2
Views: 407
Reputation: 15967
I changed your hash_tree
to open structs so I could work with it but I think I got what you are after:
require 'ostruct'
hash_tree = {
OpenStruct.new(id: 1, title: "foo") => {},
OpenStruct.new(id: 2, title: "bar") => {
OpenStruct.new(id: 3, title: "baz") => {
OpenStruct.new(id: 4, title: "qux") => {}
}
},
OpenStruct.new(id: 5, title: "norf") => {}
}
def flat_tree(hash, depth = 0)
hash.each_with_object([]) do |(obj, v), results|
results << { value: obj.id, text: obj.title, depth: depth }
results << flat_tree(v, depth + 1) if v.is_a?(Hash) && !v.empty?
end
end
puts flat_tree(hash_tree)
output:
{:value=>1, :text=>"foo", :depth=>0}
{:value=>2, :text=>"bar", :depth=>0}
{:value=>3, :text=>"baz", :depth=>1}
{:value=>4, :text=>"qux", :depth=>2}
{:value=>5, :text=>"norf", :depth=>0}
Upvotes: 2