Python存储字典路径并回读

时间:2018-04-11 18:53:16

标签: python python-3.x

我正在循环重叠的列表(系统信息)字典并以这种格式存储密钥的完整路径:

.children[0].children[9].children[0].children[0].handle = PCI:0000:01:00.0
.children[0].children[9].children[0].children[0].description = Non-Volatile memory controller
.children[0].children[9].children[0].children[0].product = Samsung Electronics Co Ltd
.children[0].children[9].product = Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2
.children[2].product = PWS-406P-1R

接下来,读入完整路径并将其与系统信息(数据)进行比较。如何将完整路径转换为此格式?

Data['children'][0]['children'][9]['children'][0]['children'][0]['handle']
Data['children'][0]['children'][9]['product]'
Data['children'][2]['product']

我可以做类似的事情:

data = re.findall(r"\.([a-z]+)\[(\d+)\]", key, re.IGNORECASE)

[('children', '0'), ('children', '9'), ('children', '0'), ('children', '0')]
[('children', '0'), ('children', '9'), ('children', '0'), ('children', '0')]
[('children', '0'), ('children', '9'), ('children', '0'), ('children', '0')]
[('children', '0'), ('children', '9')]
[('children', '2')]

如何转换其中一个元组列表才能执行此操作:

if Data['children'][2]['product'] == expected:
    print('pass')

4 个答案:

答案 0 :(得分:1)

您可以使用2018-04-11 ----- 0 2018-04-10 ----- 0 2018-04-09 ----- 3 2018-04-08 ----- 6 2018-04-07 ----- 2 2018-04-06 ----- 0 2018-04-05 ----- 4 2018-04-04 ----- 0 2018-04-03 ----- 0 2018-04-02 ----- 0 2018-04-01 ----- 0 itertoolsfunctools库将索引链接在一起,并递归查找它们以获取最终值。

首先,我认为您应该更改正则表达式以获取最后一个getter(即operator

handle, description, product

那应该给你这个

re.findall(r"\.([a-z]+)(?:\[(\d+)\])?", key, re.IGNORECASE)

然后你可以做这样的事情来链接查找

[('children', '0'), ('children', '9'), ('product', '')]

答案 1 :(得分:0)

我现在能想到的最简单的是:

<强>代码:

s = '.children[2].product = PWS-406P-1R'
path, expected = re.sub(r'\.(\w+)', r"['\1']", s).split(' = ')
Data = {'children': ['', '', {'product': 'PWS-406P-1R'}]}

if eval(f'Data{path}') == expected:
    print('pass')

<强>输出:

pass

注意f-strings的使用,需要Python 3.6+。如果您愿意,可以将其更改为.format()

答案 2 :(得分:0)

它可以在Data结构中进行递归搜索:

s = """.children[0].children[9].children[0].children[0].handle = PCI:0000:01:00.0
.children[0].children[9].children[0].children[0].description = Non-Volatile memory controller
.children[0].children[9].children[0].children[0].product = Samsung Electronics Co Ltd
.children[0].children[9].product = Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2
.children[2].product = PWS-406P-1R
"""

import re

Data = {'children': {'0': {'children': {'9': {'children': {'0': {'children': {'0': {'handle': 'value'}}}}}}}}}

for line in s.splitlines():
    l, value = re.split(r'\s*=\s*', line)
    l = l[1:] # Remove first '.'
    keys = re.split(r'[\[\].]+', l)
    print(keys)

    lookup = Data
    for key in keys:
        if key in lookup:
            lookup = lookup[key]
        else:
            print("Key {} not found".format(key))
            raise Exception("Value not found for {}".format(".".join(keys)))

    print("Value found: " + value)

第一个拆分将键与数据(寻找=

分开

l = l[1:]删除第一个'。'

第二个拆分将所有字段分隔为一组密钥以访问数据。

然后,数据结构中有一个循环的查找。

答案 3 :(得分:0)

这是尝试这样做的另一个正则表达式:

pattern = re.compile(r'(?:\.(\w+)(?:\[(\d+)\]))|(?:\.(\w+))|(?:\s*=\s*(.+)$)')

path = '.children[0].children[9].children[0].children[0].handle = PCI:0000:01:00.0'

这就是魔术:

>>> map(lambda t: filter(None, t), pattern.findall(path))
[('children', '0'), ('children', '9'), ('children', '0'), ('children', '0'), ('handle',), ('PCI:0000:01:00.0',)]

更进一步,展平结果列表

>>> import itertools
>>> keys = map(lambda t: filter(None, t), pattern.findall(path))
>>> flatkeys = list(itertools.chain.from_iterable(map(lambda key: (key[0], int(key[1])) if len(key) > 1 else (key[0],), keys[:-1])))
>>> flatkeys
['children', 0, 'children', 9, 'children', 0, 'children', 0, 'handle']
>>> result = keys[-1][0]
>>> result
'PCI:0000:01:00.0'

现在借用表格this answer

>>> d = dict(children=[dict(children=([{} for _ in range(9)]) + [dict(children=[dict(children=[dict(handle='PCI:0000:01:00.0')])])])])
>>> d
{'children': [{'children': [{}, {}, {}, {}, {}, {}, {}, {}, {}, {'children': [{'children': [{'handle': 'PCI:0000:01:00.0'}]}]}]}]}

>>> from functools import reduce
>>> import operator
>>> assert reduce(operator.getitem, flatkeys, d) == result