2013-10-28 99 views
0

我有散列哈希顯示爲樹,就像路線。下面,我添加了預期結果和我得到的結果的示例。如何做紅寶石遞歸

例哈希:

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

我希望這樣的結果:

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 

下面是一些代碼,我提出:

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 

它返回這樣的結果:

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 

任何人都可以解釋如何做到這一點?

UPDATE

感謝答案。在這種情況下,我想出了使用這個代碼。提示是將key1設置爲以前的結果。

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

回答

2

您可以將代碼更改爲:

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 

你期望的方式工作的不同依賴於它叫做但事實並非如此。無論調用方式如何(例如,如果它是由它自己調用的),該方法都會執行相同的操作。

遞歸是將一個問題分解成較小的子問題的行爲。總會有至少兩個。在你的情況下,兩個子問題是 - 打印兩個值 - 打印鍵和迭代散列你的子問題

至少有一個需要結束遞歸否則將永遠運行下去。在上述情況下,第一個子問題結束遞歸。

+0

我想這一點,但產量並不好 –

0

你要跟蹤的路徑作爲數組:

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 
+0

更換這個'提出key.join( 「/」)+ 「/」 + key1'爲'把File.join(*鍵,KEY1)'。 。:) –

0

當我有一個嵌套結構,它可以包含不同類型的我喜歡創造一個case語句類,所以很容易界定什麼將會發生在不同的場景中。

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('/')}