我已经尝试了几种在堆栈溢出时找到的解决方案,但是当从字典移动到文件列表时,我要么在分支的末尾得到空字典,要么以文件标记结束。
问题:一个python列表对象
paths =[/etc/bluetooth/rfcomm.conf.dpkg-remove
/etc/bluetooth/serial.conf.dpkg-remove
/etc/bluetooth/input.conf
/etc/bluetooth/audio.conf.dpkg-remove
/etc/bluetooth/network.conf
/etc/bluetooth/main.conf
/etc/fish
/etc/fish/completions
/etc/fish/completions/task.fish]
expected output:
{"etc" :
{"bluetooth" :
["rfcomm.conf.dpkg-remove",
"serial.conf.dpkg-remove",
"input.conf",
"audio.conf.dpkg-remove",
"network.conf",
"main.conf"],
"fish" :
{"completions" : "task.fish"}}}
我发现我可以使用以下方法在 javascript 中输出:Parse string of file path to json object
有没有办法使用 dafaultdict 创建没有任何前面文本的叶子列表?
这让我最接近我正在寻找的东西,但我在每个节点上都留下了文件标记(defaultdict(dict,((FILE_MARKER,[]),)))。
from collections import defaultdict
FILE_MARKER = '<files>'
def attach(branch, trunk):
'''
Insert a branch of directories on its trunk.
'''
parts = branch.split('/', 1)
if len(parts) == 1: # branch is a file
trunk[FILE_MARKER].append(parts[0])
else:
node, others = parts
if node not in trunk:
trunk[node] = defaultdict(dict, ((FILE_MARKER, []),))
attach(others, trunk[node])
代码
from pprint import pprint as pp # For pretty printing nested dictioanry
def make_path(paths):
# Sort so deepest paths are first
paths = sorted(paths, key = lambda s: len(s.lstrip('/').split('/')), reverse = True)
tree_path = {}
for path in paths:
# Split into list and remove leading '/' if present
levels = path.lstrip('/').split("/")
file = levels.pop()
acc = tree_path
for i, p in enumerate(levels, start = 1):
if i == len(levels):
# Reached termination of a path
# Use current terminal object is present, else use list
acc[p] = acc[p] if p in acc else []
if isinstance(acc[p], list):
# Only append if we are at a list
acc[p].append(file)
else:
# Exaand with dictionary by default
acc.setdefault(p, {})
acc = acc[p]
return tree_path
用法
示例 1
paths =['/etc/bluetooth/rfcomm.conf.dpkg-remove',
'/etc/bluetooth/serial.conf.dpkg-remove',
'/etc/bluetooth/input.conf',
'/etc/bluetooth/audio.conf.dpkg-remove',
'/etc/bluetooth/network.conf',
'/etc/bluetooth/main.conf',
'/etc/fish',
'/etc/fish/completions',
'/etc/fish/completions/task.fish']
res = make_path(paths)
pp(res) # Pretty print result
输出
{'etc': {'bluetooth': ['rfcomm.conf.dpkg-remove',
'serial.conf.dpkg-remove',
'input.conf',
'audio.conf.dpkg-remove',
'network.conf',
'main.conf'],
'fish': {'completions': ['task.fish']}}}
示例 2
paths = [
"path1/subpath1/file111.doc",
"path1/subpath1/file112.doc",
"path1/subpath2/file121.doc",
"path1/subpath2/file122.doc",
"path2/subpath1/file211.doc",
"path2/subpath1/file212.doc",
"path2/subpath2/file221.doc",
"path2/subpath2/file222.doc",
"path2/additionalpath3/additionalpath1/file2311.doc"
]
res = make_path(paths)
pp(res) # Pretty print result
输出
{'path1': {'subpath1': ['file111.doc', 'file112.doc'],
'subpath2': ['file121.doc', 'file122.doc']},
'path2': {'additionalpath3': {'additionalpath1': ['file2311.doc']},
'subpath1': ['file211.doc', 'file212.doc'],
'subpath2': ['file221.doc', 'file222.doc']}}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句