我有一个按数组排序的文件列表,如:
arr = ["./a.txt", "./b.txt", "./bar/z.php", "./foo/hello/y.php", "./foo/x.php"]
如何创建一个dynatree对象呢? 它的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:这个问题可能看起来很懒散,但我现在花了20多个小时来解决这个问题。所以任何帮助将不胜感激。感谢。
答案 0 :(得分:2)
我喜欢选择更模块化的方法。首先,我构建一个方法make_tree
,将文件路径列表转换为嵌套哈希:
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
以下是一个示例 - 此输出稍后将仅用作中间结果:
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"=>{}}}}
然后,我们可以编写一个函数将这个嵌套的哈希转换为“dynatree”表示:
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 = 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"}]}]}]
答案 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