制作嵌套字典,不平整

时间:2016-09-14 15:01:23

标签: python python-3.x dictionary

我有一个包含键和值的列表列表,如下所示:

[
  ['mounts:device', '/dev/sda3'],
  ['mounts:fstype:[0]', 'ext1'],
  ['mounts:fstype:[1]', 'ext3']
]

我可以轻松地将列表更改为此

(列表不以':'分隔)

[
  ['mounts:device', '/dev/sda3'],
  ['mounts:fstype[0]', 'ext1'],
  ['mounts:fstype[1]', 'ext3']
]

无论什么更适合这个问题:
问题是要创建一个字典:

{
'mounts': {
    'device': '/dev/sda3',
    'fstype': [
        'ext1',
        'ext3'
    ]
}

还应该可以在列表中包含列表,例如:

['mounts:test:lala:fstype[0][0]', 'abc']

['mounts:test:lala:fstype:[0]:[0]', 'abc']

这是我到目前为止所做的:

def unflatten(pair_list):
    root = {}
    for pair in pair_list:
        context = root
        key_list = pair[0].split(':')
        key_list_last_item = key_list.pop()
        for key in key_list:
            if key not in context:
                context[key] = {}
            context = context[key]
        context[key_list_last_item] = pair[1]
    return root

根据这个答案https://stackoverflow.com/a/18648007/5413035,但根据要求,我需要在混合中使用recursivness和列表

提前致谢

2 个答案:

答案 0 :(得分:1)

以下是使用dict的解决方案:

import collections

def tree():
    return collections.defaultdict(tree)


def unflatten(pair_list):
    root = tree()
    for mount, path in pair_list:
        parts = mount.split(":")
        curr = root
        for part in parts[:-1]:
            index = int(part[1:-1]) if part[0] == "[" else part
            curr = curr[index]
        part = parts[-1]
        index = int(part[1:-1]) if part[0] == "[" else part
        curr[index] = path
    return root

使用以下输入:

pair_list = [
  ['mounts:device', '/dev/sda3'],
  ['mounts:fstype:[0]', 'ext1'],
  ['mounts:fstype:[1]', 'ext3'],
  ['mounts:test:lala:fstype:[0]:[0]', 'abc']
]

你会得到:

{
    "mounts": {
        "fstype": {
            "0": "ext1",
            "1": "ext3"
        },
        "test": {
            "lala": {
                "fstype": {
                    "0": {
                        "0": "abc"
                    }
                }
            }
        },
        "device": "/dev/sda3"
    }
}

然后你可以使用下面的递归函数make_list来转换list中的整数索引。

def make_list(root):
    if isinstance(root, str):
        return root
    keys = list(root.keys())
    if all(isinstance(k, int) for k in keys):
        values = [None] * (max(keys) + 1)
        for k in keys:
            values[k] = make_list(root[k])
        return values
    else:
        return {k: make_list(v) for k, v in root.items()}

以下是pair_list

的结果
flat = unflatten(pair_list)
flat = make_list(flat)

你会得到:

{'mounts': {'device': '/dev/sda3',
            'fstype': ['ext1', 'ext3'],
            'test': {'lala': {'fstype': [['abc']]}}}}

没事吗?

答案 1 :(得分:0)

input1=[
  ['mounts:device', '/dev/sda3'],
  ['mounts:fstype:[0]', 'ext1'],
  ['mounts:fstype:[1]', 'ext3']
]
input2={x[1]:x[0].split(':')[1] for x in input1}
input3=['ext3', 'ext1', '/dev/sda3']
input4=['fstype', 'fstype', 'device']
res={}
for x,y in zip(input3, input4):
    res.setdefault(y,[]).append(x)
res1=res.keys()
res2=res.values()
res3=[x[0] for x in res2 if len(x)==1]+[x for x in res2 if len(x)>1]
result=dict(zip(res1,res3))

print result

输出:

{'device': '/dev/sda3', 'fstype': ['ext3', 'ext1']}