Reputation: 414
I have the following table in a yaml format:
:first_directory:
:component1:
- component1.c
- component1.h
:component2:
:component2_A:
:src:
- component2_A.c
:inc:
- component2_A.h
When I print the content of the hash I get:
{:first_directory=>{:component1=>["component1.c", "component1.h"], :component2=>{:component2_A=>{:src=>["component2_A.c"], :inc=>["component2_A.h"]}}}}
Now I want to be able to create strings to concatenate all the possible values of a hash hierarchy and split it using a character. What I would like to generate are strings that look like this:
first_directory/component1/component1.c
first_directory/component1/component1.h
first_directory/component2/component2_A/src/component2_A.c
first_directory/component2/component2_A/inc/component2_A.h
What would be the cleanest and best way to achieve this?
Upvotes: 3
Views: 146
Reputation: 969
This method should work best way:
def print_hash(hash_node, prev_string=nil)
if hash_node.class == Array
hash_node.each {|element| puts "#{prev_string}#{element}"}
else # it is an inner hash
hash_node.each do |key, value|
print_hash(value, "#{prev_string}#{key}/")
end
end
end
print_hash(content_as_a_hash)
Test run:
content_as_a_hash = {:first_directory=>{:component1=>["component1.c", "component1.h"], :component2=>{:component2_A=>{:src=>["component2_A.c"], :inc=>["component2_A.h"]}}}}
print_hash(content_as_a_hash)
Results:
first_directory/component1/component1.c
first_directory/component1/component1.h
first_directory/component2/component2_A/src/component2_A.c
first_directory/component2/component2_A/inc/component2_A.h
Upvotes: 5
Reputation: 110755
As the YAML string uses indentation to indicate structure, you could obtain the desired result by operating on the string directly, employing a stack.
arr=<<_.lines
:first_directory:
:component1:
- component1.c
- component1.h
:component2:
:component2_A:
:src:
- component2_A.c
:inc:
- component2_A.h
_
#=> [":first_directory:\n",
# " :component1:\n",
# " - component1.c\n",
# " - component1.h\n",
# " :component2:\n",
# " :component2_A:\n",
# " :src:\n",
# " - component2_A.c\n",
# " :inc:\n",
# " - component2_A.h\n"]
def rollup(stack)
stack.transpose.last.join('/')
end
stack = []
arr.each_with_object([]) do |line,arr|
indent = line =~ /\S/
line.gsub!(/[:\s-]/, '')
if stack.any? && indent <= stack.last.first
arr << rollup(stack)
stack.select! { |ind,_| ind < indent }
end
stack << [indent, line]
end << rollup(stack)
#=> ["first_directory/component1/component1.c",
# "first_directory/component1/component1.h",
# "first_directory/component2/component2_A/src/component2_A.c",
# "first_directory/component2/component2_A/inc/component2_A.h"]
Upvotes: 3