2014-09-05 9 views
1

에 대한 해시의 배열을 만들? 이 질문은 게으른 게시물을 보일 수 있습니다,하지만 지금이 해결 20 개 이상의 시간을 보냈습니다 :, 동적으로 내가 좋아하는, 배열 정렬 파일의 목록을 dynatree

[{"name"=>".", "title" => ".", "isDir" => true, "children" => 
    [{"name"=>"a.txt", "title" => "a.txt"}, 
    {"name"=>"b.txt", "title" => "b.txt"}, 
    {"name" => "bar", "title"=>"bar", "isDir"=>true, "children" => 
     [{"name" => "z.php", "title" => "z.php"}, 
     {"name" => "foo", "title" => "foo", "isDir" => true, "children" => 
      [{"name" => "x.php", "title" => "x.php"}, 
      { "name" => "hello", "title" => "hello", "children" => 
       [{"name" => "y.php", "title"=>"y.php"} 
       ] 
      } 
      ] 
     } 
     ] 
    } 
    ] 
}] 

PS : 그것을위한 dynatree 객체처럼 보일 것입니다. 그래서 어떤 도움을 주시면 감사하겠습니다. 감사.

+1

귀하의 요구는 항상 .. * 터프 * ... :-) –

답변

1

제 아이디어는 각 경로를 반복하는 것입니다. 각 경로는 /으로 분할됩니다. 마지막 부분은 파일, 기타 - 디렉토리입니다.

이미 추가되지 않은 한 새 부분을 추가하면서 각 부분을 살펴 봅니다. 각 반복의 끝에서 나는 문맥을 다음 수준으로 바꾼다 - children 마지막 디렉토리의 배열.

파일이 마지막 부분입니다. 간단히 말해서 현재 컨텍스트에 파일을 추가합니다.

arr = ["./a.txt", "./b.txt", "./bar/z.php", "./foo/hello/y.php", "./foo/x.php"] 

tree = [] 

arr.each do |path| 
    # start at the beginning on each iteration 
    current_level = tree 

    # split path by '/' 
    splitted_path = path.split('/') 

    # remember the size of parts in path to distinct files from folders 
    size = splitted_path.size 

    # iterate over each part of a path 
    splitted_path.each_with_index do |node, i| 
    if i != size - 1 
     # current node is path 
     # detect if it is already in the array 
     unless current_level.detect { |n| n['name'] == node } 
     # if not - append it to array 
     current_level << { 
      'name' => node, 
      'title' => node, 
      'isDir' => true, 
      'children' => [] 
     } 
     end 
     # set the current level to the new node's children array 
     current_level = current_level.detect { |n| n['name'] == node }['children'] 
    else 
     # node is a file - append it to the children array on current level 
     current_level << { 
     'name' => node, 
     'title' => node 
     } 
    end 
    end 
end 

tree 
+0

그것은 좋아 보여요. 나는 그저 더 많은 예제와 구석들로 그것을 검증 할뿐입니다. 고마워 +1 – shivam

2

저는 모듈 식 접근 방식을 선호합니다.

paths = ["./a.txt", "./b.txt", "./bar/z.php", "./foo/hello/y.php", "./foo/x.php"] 
tree = make_tree(paths) 
#=> {"."=> 
# {"a.txt"=>{}, 
#  "b.txt"=>{}, 
#  "bar"=>{"z.php"=>{}}, 
#  "foo"=>{"hello"=>{"y.php"=>{}}, "x.php"=>{}}}} 
: -이 출력은 나중에 중간 결과로 사용됩니다 여기에
require 'pathname' 

def insert_node(tree, parts) 
    head, *tail = parts 
    tree[head] ||= {} 
    insert_node tree[head], tail unless tail.empty? 
    tree 
end 

def make_tree(paths) 
    paths.reduce({}) do |tree, file| 
    insert_node tree, Pathname(file).each_filename.to_a 
    end 
end 

은 예입니다 : 첫째, 중첩 된 해시 파일 경로의 목록을 변환하는 방법 make_tree을 구축 할 것

def make_dynatree(tree) 
    tree.map do |node, subtree| 
    if subtree.empty? 
     {"name" => node, "title" => node} 
    else 
     {"name" => node, "title" => node, "isDir" => true, "children" => make_dynatree(subtree)} 
    end 
    end 
end 

그리고 마지막으로 :

다음, 우리는 "dynatree"표현으로이 중첩 된 해시를 변환하는 기능을 쓸 수

dynatree = make_dynatree(tree) 
#=> [{"name"=>".", "title"=>".", "isDir"=>true, "children"=> 
#  [{"name"=>"a.txt", "title"=>"a.txt"}, 
#  {"name"=>"b.txt", "title"=>"b.txt"}, 
#  {"name"=>"bar", "title"=>"bar", "isDir"=>true, "children"=>[ 
#  {"name"=>"z.php", "title"=>"z.php"}]}, 
#  {"name"=>"foo", "title"=>"foo", "isDir"=>true, "children"=>[ 
#  {"name"=>"hello", "title"=>"hello", "isDir"=>true, "children"=>[ 
#   {"name"=>"y.php", "title"=>"y.php"}]}, 
#   {"name"=>"x.php", "title"=>"x.php"}]}]}] 
+0

멋져 보입니다. 그리고 동시에 쉽게 이해할 수 있습니다. – shivam

+0

조금 더 정리했습니다 ... –