如何在Python中将列表转换为嵌套dict
需要转x:如何在Python中将列表转换为嵌套dict,python,list,dictionary,nested,Python,List,Dictionary,Nested,需要转x: X = [['A', 'B', 'C'], ['A', 'B', 'D']] 进入Y: Y = {'A': {'B': {'C','D'}}} 更具体地说,我需要从绝对路径列表创建文件夹和文件树,如下所示: paths = ['xyz/123/file.txt', 'abc/456/otherfile.txt'] 其中,根据伪示例中的['A',B',C'],每个路径都被拆分(“/”) 由于这表示文件和文件夹,显然,在同一级别(数组的索引)上,相同名称的字符串不能重复 您的问题陈
X = [['A', 'B', 'C'], ['A', 'B', 'D']]
进入Y:
Y = {'A': {'B': {'C','D'}}}
更具体地说,我需要从绝对路径列表创建文件夹和文件树,如下所示:
paths = ['xyz/123/file.txt', 'abc/456/otherfile.txt']
其中,根据伪示例中的['A',B',C']
,每个路径都被拆分(“/”)
由于这表示文件和文件夹,显然,在同一级别(数组的索引)上,相同名称的字符串不能重复 您的问题陈述在逻辑上不一致。如果你真的想
['xyz/123/file.txt','abc/456/otherfile.txt']
改为
{'xyz':{'123':'file.txt},'abc':{'456':'otherfile.txt'}
然后,您必须回答如何将没有前导文件夹的路径“abc.txt”插入到该数据结构中。顶层字典键是空字符串吗?假设
{C',D'}
表示集合(['C',D'])
并且您的Python版本支持dict comprehension
和集合comprehension
,下面是一个丑陋但有效的解决方案:
>>> tr = [[1, 2, 3], [1, 2, 4], [5, 6, 7]]
>>> {a[0]: {b[1]: {c[2] for c in [y for y in tr if y[1] == b[1]]} for b in [x for x in tr if x[0] == a[0]]} for a in tr}
{1: {2: set([3, 4])}, 5: {6: set([7])}}
至于你的例子:
>>> X = [['A', 'B', 'C'], ['A', 'B', 'D']]
>>> {a[0]: {b[1]: {c[2] for c in [y for y in X if y[1] == b[1]]} for b in [x for x in X if x[0] == a[0]]} for a in X}
{'A': {'B': set(['C', 'D'])}}
但请不要在实际应用程序中使用它:)
更新:这里有一个适用于任意深度的:
>>> def todict(lst, d=0):
... print lst, d
... if d > len(lst):
... return {}
... return {a[d]: todict([x for x in X if x[d] == a[d]], d+1) for a in lst}
...
>>> todict(X)
{'A': {'B': {'C': {}, 'D': {}}}}
这应该非常接近您所需要的:
def path_to_dict(path):
parts = path.split('/')
def pack(parts):
if len(parts) == 1:
return parts
elif len(parts):
return {parts[0]: pack(parts[1:])}
return parts
return pack(parts)
if __name__ == '__main__':
paths = ['xyz/123/file.txt', 'abc/456/otherfile.txt']
for path in paths:
print '%s -> %s' % (path, path_to_dict(path))
结果:
xyz/123/file.txt -> {'xyz': {'123': ['file.txt']}}
abc/456/otherfile.txt -> {'abc': {'456': ['otherfile.txt']}}
这就留下了包含
{'A':{'B':{'C':{},'d':{}},'W':{'Y':{'Z':{},'X':{}
。任何包含空字典的条目都是一个文件或一个空目录。我在twitter上被问及这个问题,并使用函数式编程提出了这个巧妙的解决方案,我想我不妨在这里分享一下
from functools import reduce
X = [['A', 'B', 'C'], ['A', 'B', 'D']]
Y = [reduce(lambda x, y: {y:x}, Y[::-1]) for Y in X]
返回:
[{'A': {'B': 'C'}}, {'A': {'B': 'D'}}]
{'A': {'B': 'C'}}
如所愿
对于一个更简单的问题,如果您有一个列表要用嵌套键表示为dict,那么这就足够了:
from functools import reduce
X = ['A', 'B', 'C']
reduce(lambda x, y: {y:x}, X[::-1])
返回:
[{'A': {'B': 'C'}}, {'A': {'B': 'D'}}]
{'A': {'B': 'C'}}
这是什么
{'C','D'}
您试图用嵌套的dict解决什么问题?如果文件夹A包含目录B和文件X怎么办?该如何表示?这是否可以接受<代码>{'A':{'B':{'C':{},'D':{}}}更一致的是,Y={'A':{'B':{'C':{},'D':{}}也不适用于任意深度,这可能是一个要求。@true-我认为这不是一个要求,但可能是。我是否应该想出一个更可怕的单行侠?:)哈,那就太可怕了。我认为Matt有这个想法——它必须递归地完成。你如何加入所有的字典,比如如果你有其他路径,如xyz/123/b.a
和abc/sss/ooo/1.a
与这些路径重叠?如果'xyz'
包含目录和文件呢?Matt,我正要问与agf相同的问题。到目前为止,我自己做到了。我真的需要一本字典。会有重叠,所以我不能完全替换节点,实际上需要在每一层进行合并。深度合并指令:如果在顶层有一个名为abc.txt的文件,它将是一个带有“xyz”和“abc”的对等文件,如{'xyz':{…},'abc':{…},'abc.txt:{}。对于空的{},表示它是一个叶子,如果某个东西“看起来”像文件或文件夹,则无关紧要。最后一个是文件,其余是文件夹。顺便说一句,这不是真正的文件系统。当前的_级别在哪里添加到d?@Tyler Hilbert当前的_级别是d
!表达式current_level=d
不复制d
,它只是创建一个名为current_level
;的对d
的新引用。)如果current\u level
是一个副本,上面的代码将不起作用,创建方式如下:current\u level=d[:]
或类似这样:current\u level=copy.deepcopy(d)
,但既然不是这样,它只会起作用@tsveti_iko如果它是一个参考,为什么行current_level=current_level[部分]
只修改current_level
,而不修改d
?我已经检查了调试器,在这个阶段之后(例如,当我们在第一个元素A
),我们将得到:current_level={}
,而d={'A':{}}
。谢谢