我正在尝试从路径列表中填充python字典(目的是创建一个ttk.treview(:
paths = ["\hihi", "\hihi\hoho\huhu", "\hihi\hoho\haha", "\haha", "\huhu"]
我想创建这个字典(json在这里序列化(:
{
"haha": {},
"hihi": {
"hoho": {
"huhu": 0
},
"huhu": {
"haha": 0
}
},
"huhu": {}
}
最好的方法是什么?我尝试使用 for 循环(递归循环?(、字典理解和 dpath,但我没有有效的结果。
我的代码变大了:
split = paths.split("\")
del split[0]
dict = {}
?
提前非常感谢
您可以使用defaultdict
:
def make_empty_default_dict():
return defaultdict(make_empty_default_dict)
定义添加路径的方式:
def add_path(pth, dct):
if pth:
subdict = dct[pth[0]]
return add_path(pth[1:], subdict)
else:
return dct
然后用键填充默认字典:
d = make_empty_default_dict()
for path in paths:
d = add_path(path.split("\"), d)
我有一个递归解决方案的替代方案。对于每个路径:
- 将光标放在目标字典的根目录
- 搜索顺序:向前移动光标,直到找到路径的 0 或缺失部分
- 构建顺序:添加一个空字典并将光标移到该字典上,直到点击最后一部分。
- 最后一部分需要对 0 进行特殊处理。
代码如下:
def build_paths(paths, d={}):
for path in paths:
parts = path.split("\")[1:] # remove the part before
cursor = d
search = True
for part in parts[:-1]:
if search:
if part not in cursor or not cursor[part]: # not found or 0
cursor[part] = {} # set a new dict
search = False
else:
cursor[part] = {}
cursor = cursor[part] # advance one level deeper in the dict
cursor[parts[-1]] = 0 # close with a 0
return d
它比@xtofl的递归快,但没那么快。timeit
:
iterative: 6.169872568580601
recursive: 17.209112331781498
您可以将递归与itertools.groupby
一起使用:
import itertools
paths = ["\hihi", "\hihi\hoho\huhu", "\hihi\hoho\haha", "\haha", "\huhu"]
new_paths = [list(filter(None, i.split('\'))) for i in paths]
def update_output(f):
def wrapper(_d):
result = f(_d)
final = lambda x, level = 0:{a:{} if not level and not b else b if not b else final(b, level+1) for a, b in x.items()}
return final(result)
return wrapper
@update_output
def full_directory(data):
def files(d):
return {a:(lambda x:0 if len(x) == 1 else files([i[1:] for i in filter(lambda y:len(y) != 1 or y[0] != a, x)]))(list(b)) for a, b in itertools.groupby(sorted(d, key=lambda x:x[0]), key=lambda x:x[0])}
return files(data)
print(full_directory(new_paths))
输出:
{'haha': {}, 'hihi': {'hoho': {'haha': 0, 'huhu': 0}}, 'huhu': {}}
我发现这个:http://connor-johnson.com/2015/02/28/generate-a-tree-structure-in-python/
效果很好!所以代码:
def add(t, path):
for node in path:
t = t[node]
Tree = lambda: defaultdict(Tree)
t = Tree()
paths = ["\hihi", "\hihi\hoho\huhu", "\hihi\hoho\haha", "\haha", "\huhu"]
for path in paths:
split = path.split("\")
del split[0]
for elt in split:
add(t, split)
dicts = lambda t: { k:dicts(t[k]) for k in t }
print(json.dumps(dicts(t), indent=4))