Python:从路径列表创建嵌套字典

0 投票
1 回答
2309 浏览
提问于 2025-04-15 22:09

我有一个元组的列表,长得像这样(这里简化了一下,实际上有超过14,000个这样的元组,路径比Obj.part复杂得多)

[ (Obj1.part1, {<SPEC>}), (Obj1.partN, {<SPEC>}), (ObjK.partN, {<SPEC>}) ]

其中Obj的范围是1到1000,part的范围是0到2000。这些“键”都有一个与之相关的规格字典,作为查找参考,用来检查另一个二进制文件。规格字典包含的信息有位偏移、位大小和路径ObjK.partN指向的数据的C类型。

举个例子:Obj4.part500可能有这样的规格,{'size':32, 'offset':128, 'type':'int'},这让我知道要在二进制文件中访问Obj4.part500,我必须从偏移128处解包32位的数据。

现在,我想把我的字符串列表变成一个嵌套字典,简化后的样子会是这样的:

data = { 'Obj1' : {'part1':{spec}, 'partN':{spec} }, 
         'ObjK' : {'part1':{spec}, 'partN':{spec} }
       }

为此,我目前在做两件事,第一,我使用一个dotdict类,这样我就可以用点符号来获取和设置字典的值。这个类长这样:

class dotdict(dict):
    def __getattr__(self, attr):
        return self.get(attr, None)
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

创建嵌套“dotdict”的方法是这样的:

def addPath(self, spec, parts, base):
    if len(parts) > 1:
        item = base.setdefault(parts[0], dotdict())
        self.addPath(spec, parts[1:], item)
    else:
        item = base.setdefault(parts[0], spec)
    return base

然后我只需做类似这样的事情:

for path, spec in paths:
    self.lookup = dotdict()
    self.addPath(spec, path.split("."), self.lookup)

所以,最后
self.lookup.Obj4.part500指向这个规格。

有没有更好(更符合Python风格)的方法来做到这一点?

1 个回答

8

如果你不想用点号来访问规格,可以直接把它们放进字典里。在下面的代码中,名字 d 用来记录在路径上访问到的最里层的字典:

specs = {}
for path, spec in paths:
    parts = path.split('.')
    d = specs
    for p in parts[:-1]:
        d = d.setdefault(p, {})
    d[parts[-1]] = spec

如果每条路径只有两个部分(比如说 ObjNpartN),你可以这样做:

specs = {}
for path, spec in paths:
    [obj, part] = path.split('.')
    specs.setdefault(obj, {})[part] = spec

撰写回答