我希望从列表列表中创建一个JSON类型的嵌套字典。列表包含完整的目录路径,但是我将它们分解为各自的组件,因为我认为这样会使嵌套字典的创建更加容易。
示例列表:
["root", "dir1", "file.txt"]
预期结果:
{
"type": "directory",
"name": "root",
"children": [
{
"type": "directory",
"name": "dir1",
"children": [
{
"type": "file",
"name": "file.txt",
}
]
}
]
}
我尝试使用递归方法,但无法完全到达递归方法(递归方法的新手,我的头脑不断旋转)。我还尝试了一种迭代方法,该方法是我在这里找到的一个想法(堆栈溢出),它可以颠倒列表并向后构建dict,虽然我可以使用,但无法解决其中一个解决方案要求,即代码可以遍历列表列表时处理部分目录路径中的重复项。 例如,从上一个示例开始,下一个输入的列表是:-
["root", "dir1", "dir2", "file2.txt"]
,它需要构建到JSON字典上才能产生此结果:-
{
"type": "directory",
"name": "root",
"children": [
{
"type": "directory",
"name": "dir1",
"children": [
{
"type": "file",
"name": "file.txt",
}
{
"type": "directory",
"name": "dir2",
"children": [
{
"type": "file",
"name": "file2.txt"
}
]
}
]
}
]
}
,依此类推,包含目录路径的列表数量未知。 谢谢。
答案 0 :(得分:1)
这是一个幼稚的递归解决方案,它简单地遍历树结构,并根据需要添加子项,直到到达path
的最后一个元素(假定是文件)为止。
import json
def path_to_json(path, root):
if path:
curr = path.pop(0)
if not root:
root["type"] = "file"
root["name"] = curr
if path:
root["children"] = [{}]
root["type"] = "directory"
path_to_json(path, root["children"][0])
elif path:
try:
i = [x["name"] for x in root["children"]].index(path[0])
path_to_json(path, root["children"][i])
except ValueError:
root["children"].append({})
path_to_json(path, root["children"][-1])
return root
if __name__ == "__main__":
paths = [["root", "dir1", "file.txt"],
["root", "dir1", "dir2", "file2.txt"]]
result = {}
print(json.dumps([path_to_json(x, result) for x in paths][0], indent=4))
输出:
{
"type": "directory",
"name": "root",
"children": [
{
"type": "directory",
"name": "dir1",
"children": [
{
"type": "file",
"name": "file.txt"
},
{
"type": "directory",
"name": "dir2",
"children": [
{
"type": "file",
"name": "file2.txt"
}
]
}
]
}
]
}
答案 1 :(得分:1)
使用itertools.groupby
的递归解决方案如下(假定所有路径都是绝对路径)。想法是按路径列表中的第一个元素对路径进行分组。这会将相似的目录根分组在一起,从而使我们可以在该组上递归调用函数。
还请注意,文件名不能在目录中重复,因此所有文件将按groupby
分组为单个元素列表:
from itertools import groupby
from operator import itemgetter
def build_dict(paths):
if len(paths) == 1 and len(paths[0]) == 1:
return {"type": "file", "name": paths[0][0]}
dirname = paths[0][0]
d = {"type": "directory", "name": dirname, "children": []}
for k, g in groupby(sorted([p[1:] for p in paths], key=itemgetter(0)),
key=itemgetter(0)):
d["children"].append(build_dict(list(g)))
return d
paths = [["root", "dir1", "file.txt"], ["root", "dir1", "dir2", "file2.txt"]]
print(build_dict(paths))
输出
{
"type": "directory",
"name": "root",
"children": [
{
"type": "directory",
"name": "dir1",
"children": [
{
"type": "directory",
"name": "dir2",
"children": [
{
"type": "file",
"name": "file2.txt"
}
]
},
{
"type": "file",
"name": "file.txt"
}
]
}
]
}
答案 2 :(得分:0)
鉴于没有提供太多细节,这是一个使用引用输入每个嵌套dict
In [537]: structure = ["root", "dir1", "dir2", "file2.txt"]
In [538]: d = {}
# Create a reference to the current dict
In [541]: curr = d
In [542]: for i, s in enumerate(structure):
...: curr['name'] = s
...: if i != len(structure) - 1:
...: curr['type'] = 'directory'
...: curr['children'] = {}
...: curr = curr['children'] # New reference is the child dict
...: else:
...: curr['type'] = 'file'
...:
In [544]: from pprint import pprint
In [545]: pprint(d)
{'children': {'children': {'children': {'name': 'file2.txt', 'type': 'file'},
'name': 'dir2',
'type': 'directory'},
'name': 'dir1',
'type': 'directory'},
'name': 'root',
'type': 'directory'}
我不知道这是否可以解决您的所有问题,因为规格不是很详细