0

I have a hash of hashes to display as tree, something like routes. Below, I added an example of an expected result and the result I got.

Example hash:

hash = {
          'movies' => {
            'action' => {
              '2007' => ['video1.avi', 'x.wmv'],
              '2008' => ['']
            },
            'comedy' => {
              '2007' => [],
              '2008' => ['y.avi']
            }
          },
          'audio' => {
            'rock' => {
              '2003' => [],
              '2004' => ['group', 'group1']
            }
          }
        }

I expected this result:

movies
movies\action
movies\action\2007
movies\action\2007\video1.avi
movies\action\2007\x.wmv
movies\action\2008
movies\comedy\2007
movies\comedy\2008
movies\comedy\2008\y.avi
audio
audio\rock\2003
audio\rock\2004
audio\rock\2004\group
audio\rock\2004\group1

Here are some code I made:

def meth(key, val)
  val.each do |key1, val1|
    puts "#{key}/#{key1}"
    meth(key1, val1) if val1
  end
end

hash.each do |key, val|
  puts key
  meth(key,val)
end

It returns this result:

movies
movies/action
action/2007
2007/video1.avi
2007/x.wmv
action/2008
2008/
movies/comedy
comedy/2007
comedy/2008
2008/y.avi
audio
audio/rock
rock/2003
rock/2004
2004/group
2004/group1

Can anybody explain how to do this?

UPDATE

Thanks for answers. In this case I figured out using this code. The hint was to set key1 to the previous result.

def meth key, val
  val.each do |key1, val1|
    puts "#{key}/#{key1}"
    key1 = "#{key}/#{key1}"
    meth(key1, val1) if val1
  end
end

3 Answers 3

2

you could change the code to:

def meth(key, val)
  val.each do |key1, val1|
    puts "#{key}/"
    if (val1 && val1.is_a?(Hash))
       meth(key1, val1)
    else
       puts "#{val1}"
    end
  end
end

you are expecting the method to work differently dependant on where it's called but that's not the case. The method does the same regardless of where it's called (e.g. if it's called by it self).

Recursion is the act of deviding one problem into smaller subproblems. There'll always be at least two. In your case the two sub problems is - print two values - print the key and iterate a hash

At least one of your subproblems need to end the recursion otherwise it will run forever. In the above case the first subproblem ends the recursion.

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

Comments

0

You have to keep track of the path as an array:

def meth key, val
  val.each do |key1, val1|
    puts key.join("/")+"/"+key1
    meth(key + [key1], val1) if val1
  end
end

meth [], root_of_hash

1 Comment

Replace this puts key.join("/")+"/"+key1 as puts File.join(*key,key1).. :)
0

When I have a nested structure that can contain different types of classes I like to create a case statement so it is easy to define what will happen in different scenarios.

def print_tree(input, path=[])
    case input
      when Hash then  input.flat_map{|x,y| print_tree(y, path+[x])}
      when Array then input.empty? ? [path] : input.map{|x| path+[x]}
    end
end
puts print_tree(my_hash).map{|z|z.join('/')}

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.