如何在Python中将列表转换为嵌套字典

发布于 2024-12-08 03:17:47 字数 397 浏览 1 评论 0原文

需要将 x:

X = [['A', 'B', 'C'], ['A', 'B', 'D']]

转换为 Y:

Y = {'A': {'B': {'C','D'}}}

更具体地说,我需要从绝对路径列表创建文件夹和文件树,如下所示:

paths = ['xyz/123/file.txt', 'abc/456/otherfile.txt']

其中,每个路径都是 split("/"),如伪示例中的 ['A', 'B', 'C'] 所示。

由于这代表文件和文件夹,显然,在同一级别(数组的索引)上,同名字符串不能重复。

Need to turn x:

X = [['A', 'B', 'C'], ['A', 'B', 'D']]

Into Y:

Y = {'A': {'B': {'C','D'}}}

More specifically, I need to create a tree of folders and files from a list of absolute paths, which looks like this:

paths = ['xyz/123/file.txt', 'abc/456/otherfile.txt']

where, each path is split("/"), as per ['A', 'B', 'C'] in the pseudo example.

As this represents files and folders, obviously, on the same level (index of the array) same name strings can't repeat.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一曲爱恨情仇 2024-12-15 03:17:47
X = [['A', 'B', 'C'], ['A', 'B', 'D'],['W','X'],['W','Y','Z']]
d = {}

for path in X:
    current_level = d
    for part in path:
        if part not in current_level:
            current_level[part] = {}
        current_level = current_level[part]

这使得 d 包含 {'A': {'B': {'C': {}, 'D': {}}}, 'W': {'Y': {'Z': {}},“X”:{}}}。任何包含空字典的项目要么是文件,要么是空目录。

X = [['A', 'B', 'C'], ['A', 'B', 'D'],['W','X'],['W','Y','Z']]
d = {}

for path in X:
    current_level = d
    for part in path:
        if part not in current_level:
            current_level[part] = {}
        current_level = current_level[part]

This leaves us with d containing {'A': {'B': {'C': {}, 'D': {}}}, 'W': {'Y': {'Z': {}}, 'X': {}}}. Any item containing an empty dictionary is either a file or an empty directory.

卸妝后依然美 2024-12-15 03:17:47

假设 {'C', 'D'} 表示 set(['C', 'D']) 并且您的 Python 版本支持字典理解 和 设置理解,这是一个丑陋但有效的解决方案:

>>> 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': {}}}}

Assuming that {'C', 'D'} means set(['C', 'D']) and your Python version supports dict comprehension and set comprehension, here's an ugly but working solution:

>>> 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])}}

As for your example:

>>> 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'])}}

But please don't use it in a real-world application :)

UPDATE: here's one that works with arbitrary depths:

>>> 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': {}}}}
楠木可依 2024-12-15 03:17:47

您的问题陈述存在逻辑不一致。如果你真的想要
['xyz/123/file.txt', 'abc/456/otherfile.txt']

更改为
{'xyz': {'123': 'file.txt}, 'abc': {'456': 'otherfile.txt'}}

然后你必须回答路径 'abc.txt' 是如何实现的。没有前导文件夹的“txt”将被插入到此数据结构中。顶级字典键会是空字符串 '' 吗?

There is a logical inconsistency in your problem statement. If you really want
['xyz/123/file.txt', 'abc/456/otherfile.txt']

to be changed to
{'xyz': {'123': 'file.txt}, 'abc': {'456': 'otherfile.txt'}}

Then you have to answer how a path 'abc.txt' with no leading folder would be inserted into this data structure. Would the top-level dictionary key be the empty string ''?

烟柳画桥 2024-12-15 03:17:47

这应该非常接近您所需要的:

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']}}

This should be pretty close to what you need:

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))

Results in:

xyz/123/file.txt -> {'xyz': {'123': ['file.txt']}}
abc/456/otherfile.txt -> {'abc': {'456': ['otherfile.txt']}}
将军与妓 2024-12-15 03:17:47

我在 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'}}]

根据需要。

对于更简单的问题,您有一个列表想要表示为带有嵌套键的字典,这就足够了:

from functools import reduce
X = ['A', 'B', 'C']
reduce(lambda x, y: {y:x}, X[::-1])

它返回:

{'A': {'B': 'C'}}

I got asked about this question on twitter and came up with this slick solution using functional programming which I figure I might as well share here.

from functools import reduce
X = [['A', 'B', 'C'], ['A', 'B', 'D']]
Y = [reduce(lambda x, y: {y:x}, Y[::-1]) for Y in X]

which returns:

[{'A': {'B': 'C'}}, {'A': {'B': 'D'}}]

as desired.

For the simpler problem where you have one list that you want to represent as a dict with nested keys, this will suffice:

from functools import reduce
X = ['A', 'B', 'C']
reduce(lambda x, y: {y:x}, X[::-1])

which returns:

{'A': {'B': 'C'}}
源来凯始玺欢你 2024-12-15 03:17:47

首先将键与值分开

x = [['A', 'B', 'C'], ['A', 'B', 'D']]
keys = [tuple(asd[:-1]) for asd in x]
values = [asd[-1] for asd in x]

现在使用它们来填充 NestedDict

from ndicts.ndicts import NestedDict

nd = NestedDict()
for key, value in zip(keys, values):
    nd[key] = value
>>> nd
NestedDict({'A': {'B': 'D'}})
>>> nd.to_dict()
{'A': {'B': 'D'}}

要安装 ndicts pip 安装 ndicts

First split keys from values

x = [['A', 'B', 'C'], ['A', 'B', 'D']]
keys = [tuple(asd[:-1]) for asd in x]
values = [asd[-1] for asd in x]

Now use them to populate a NestedDict

from ndicts.ndicts import NestedDict

nd = NestedDict()
for key, value in zip(keys, values):
    nd[key] = value
>>> nd
NestedDict({'A': {'B': 'D'}})
>>> nd.to_dict()
{'A': {'B': 'D'}}

To install ndicts pip install ndicts

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文