2011-04-02 12 views
10

बनाने के लिए मुझे एक निर्देशिका को पार करने और jsTree नियंत्रण के साथ उपयोग करने के लिए एक पेड़ बनाने की आवश्यकता है। नियंत्रण एक JSON प्रारूप like so स्वीकार करता है। यह साफ और जल्दी होने के लिए मुझे कुछ रूबी जादू की ज़रूरत है।रूबी रिकर्सिव डायरेक्टरी ट्री

किसी भी मदद की सराहना की जाती है।

उत्तर

24

आप शायद इस (untested) की तरह कुछ करना चाहते हैं। इसे अपने पसंदीदा क्रमबद्धता पुस्तकालय के साथ जेसन में बदलें।

+0

मैंने इसे बहुत दूर जाने से रोकने के लिए एक छोटा सा परिवर्तन किया:' अगला अगर (प्रविष्टि == '..' || प्रविष्टि == '। ') ' आपकी मदद के लिए बहुत बहुत धन्यवाद। मैं वास्तव में इसकी प्रशंसा करता हूँ। – Mem

+0

आह धन्यवाद, अच्छी जगह। मैंने उपर्युक्त उत्तर में संशोधन किया है। – Glenjamin

1

रूबी के ढूँढें मॉड्यूल (require 'find') न्यूनतम है, लेकिन अच्छी तरह से निर्देशिका प्रत्यावर्तन संभालता है: http://www.ruby-doc.org/stdlib/libdoc/find/rdoc/classes/Find.html

+0

आपके त्वरित उत्तर के लिए धन्यवाद। मैं खोज का उपयोग करने की कोशिश कर रहा हूं लेकिन पेड़ के लिए जरूरी संरचना बनाने के बारे में अनिश्चित हूं (उदा। एक निर्देशिका में बच्चे हैं जो उप-निर्देशिकाएं हैं और जिनके बच्चे हैं, आदि)। – Mem

7

पहले, अपने पेड़ ले यह पत्तियों को पथ, के लिए इसी तरह की एक सूची में कन्वर्ट:

def leaves_paths tree 
    if tree[:children] 
    tree[:children].inject([]){|acc, c| 
     leaves_paths(c).each{|p| 
     acc += [[tree[:name]] + p] 
     } 
     acc 
    } 
    else 
    [[tree[:name]]] 
    end 
end 

(नहीं सुनिश्चित करें कि उपर्युक्त आपकी जेएसटी संरचना का पालन करता है, लेकिन सिद्धांत समान है।)

यहां इनपुट और आउटपुट का नमूना है:

tree = {name: 'foo', children: [ 
     {name: 'bar'}, 
     {name: 'baz', children: [ 
     {name: 'boo'}, 
     {name: 'zoo', children: [ 
      {name: 'goo'} 
     ]} 
     ]} 
    ]} 

p leaves_paths tree 
#=> [["foo", "bar"], ["foo", "baz", "boo"], ["foo", "baz", "zoo", "goo"]] 

फिर, प्रत्येक पथ के लिए, फोन FileUtils#mkdir_p:

paths = leaves_paths tree 
paths.each do |path| 
    FileUtils.mkdir_p(File.join(*path)) 
end 

और तुम ठीक किया जाना चाहिए।

संपादित करें: सरल संस्करण:

आप, पत्तियों के सूची बनाने के बस पूरे वृक्ष पार और प्रत्येक नोड के लिए एक निर्देशिका बनाने की जरूरत नहीं है:

# executes block on each tree node, recursively, passing the path to the block as argument 
def traverse_with_path tree, path = [], &block 
    path += [tree[:name]] 
    yield path 
    tree[:children].each{|c| traverse_with_path c, path, &block} if tree[:children] 
end 

traverse_with_path tree do |path| 
    FileUtils.mkdir(File.join(*path)) 
end 

EDIT2:

ओह , माफ़ कीजिए मैंने गलत समझा। तो, यहाँ डिस्क पर निर्देशिका वृक्ष के आधार पर एक हैश बनाने के लिए एक तरीका है:

Dir.glob('**/*'). # get all files below current dir 
    select{|f| 
    File.directory?(f) # only directories we need 
    }.map{|path| 
    path.split '/' # split to parts 
    }.inject({}){|acc, path| # start with empty hash 
    path.inject(acc) do |acc2,dir| # for each path part, create a child of current node 
     acc2[dir] ||= {} # and pass it as new current node 
    end 
    acc 
    } 

तो, निम्नलिखित संरचना के लिए: रिटर्न ऊपर

#$ mkdir -p foo/bar 
#$ mkdir -p baz/boo/bee 
#$ mkdir -p baz/goo 

कोड इस हैश:

{ 
    "baz"=>{ 
    "boo"=>{ 
     "bee"=>{}}, 
    "goo"=>{}}, 
    "foo"=>{ 
    "bar"=>{}}} 

आशा है कि आप इसे अपनी आवश्यकताओं के अनुरूप बनाएंगे।

def directory_hash(path, name=nil) 
    data = {:data => (name || path)} 
    data[:children] = children = [] 
    Dir.foreach(path) do |entry| 
    next if (entry == '..' || entry == '.') 
    full_path = File.join(path, entry) 
    if File.directory?(full_path) 
     children << directory_hash(full_path, entry) 
    else 
     children << entry 
    end 
    end 
    return data 
end 

रिकर्सिवली पेड़ नीचे चलना, एक हैश का निर्माण:

+0

अरे, प्रतिक्रिया के लिए बहुत बहुत धन्यवाद। मैं अपने मूल पोस्ट में अस्पष्ट हो सकता था लेकिन मुझे वास्तव में कोई निर्देशिका बनाने की आवश्यकता नहीं है लेकिन पथ के सभी मौजूदा फाइलों/निर्देशिकाओं को दोबारा सूचीबद्ध करने की आवश्यकता नहीं है। – Mem

+0

आपकी मदद के लिए बहुत बहुत धन्यवाद। कोड बहुत अच्छा काम करता है लेकिन केवल निर्देशिका को पकड़ता है, फिर भी संशोधित करने के लिए पर्याप्त सरल है। इसकी प्रशंसा करना। – Mem

+0

इसने मुझे पूरी तरह से Mkdir_p() –

1

स्वीकृत उत्तर जून 2015 तक काम नहीं किया। मैंने :data को 'text' पर बदल दिया। मैंने निर्देशिकाओं और फ़ाइलों को बाहर करने के लिए कोड को सामान्यीकृत भी किया।

def directory_hash(path, name=nil, exclude = [])         
    exclude.concat(['..', '.', '.git', '__MACOSX', '.DS_Store'])     
    data = {'text' => (name || path)}            
    data[:children] = children = []            
    Dir.foreach(path) do |entry|             
    next if exclude.include?(entry)            
    full_path = File.join(path, entry)           
    if File.directory?(full_path)            
     children << directory_hash(full_path, entry)        
    else                   
     children << {'icon' => 'jstree-file', 'text' => entry}      
    end                   
    end                   
    return data                 
end 
संबंधित मुद्दे