创建单独的字典,其中包含值列表

Posted

技术标签:

【中文标题】创建单独的字典,其中包含值列表【英文标题】:Creating separate dictionaries with a list of values in it 【发布时间】:2022-01-21 21:57:42 【问题描述】:

我有一本这样的字典:

d = 
    'hosts': [
        'hostname': 'abc', 'ip': '127.0.0.1', 'extra_check_cmd': 'check-me',
        'hostname': 'def', 'ip': '127.0.0.2', 'extra_check_cmd': 'check-it,check-this',
        'hostname': 'ijk,uvw,xyz', 'ip': '127.0.0.3,127.0.0.4,127.0.0.5', 'extra': 'check-me,check-this,check-it'
    ]

我想用它创建以下字典

d = 
    'hosts': [
        'hostname': 'abc', 'ip': '127.0.0.1', 'extra_check_cmd': 'check-me',
        'hostname': 'def', 'ip': '127.0.0.2', 'extra_check_cmd': 'check-it',
        'hostname': 'def', 'ip': '127.0.0.2', 'extra_check_cmd': 'check-this',
        'hostname': 'ijk', 'ip': '127.0.0.3', 'extra': 'check-me',
        'hostname': 'uvw', 'ip': '127.0.0.4', 'extra': 'check-me',
        'hostname': 'xyz', 'ip': '127.0.0.5', 'extra': 'check-me'
        'hostname': 'ijk', 'ip': '127.0.0.3', 'extra': 'check-it',
        'hostname': 'uvw', 'ip': '127.0.0.4', 'extra': 'check-it',
        'hostname': 'xyz', 'ip': '127.0.0.5', 'extra': 'check-it'
        'hostname': 'ijk', 'ip': '127.0.0.3', 'extra': 'check-this',
        'hostname': 'uvw', 'ip': '127.0.0.4', 'extra': 'check-this',
        'hostname': 'xyz', 'ip': '127.0.0.5', 'extra': 'check-this'
    ]

这意味着每个值列表都应该有一个单独的子字典,只要给出了值列表。

【问题讨论】:

【参考方案1】:

也许是这样的?

def expand_dict(host):
    # Create all of the possible key-value pairs for each key in the original dictionary
    kv_pairs = [[(k, v) for v in vals.split(",")] for k, vals in host.items()]
    # Find the number of dictionaries this would expand to
    max_len = max(len(p) for p in kv_pairs)
    # A list of possible values must either be the length of the number of dictionaries we expect, or length 1 so we can repeat the value max_len times
    assert all(len(pairs) in 1, max_len for pairs in kv_pairs)
    # Expand all of the length 1 value lists to length max_len
    updated_pairs = [p if len(p) == max_len else p * max_len for p in kv_pairs]
    # Return a generator of dictionaries for each of the sets of key-value pairs
    return (dict(pairs) for pairs in zip(*updated_pairs))

input_dict = 'hosts': ['hostname': 'abc', 'ip': '127.0.0.1', 'extra_check_cmd': 'check-me', 'hostname': 'def', 'ip': '127.0.0.2', 'extra_check_cmd': 'check-it,check-this', 'hostname': 'ijk,uvw,xyz', 'ip': '127.0.0.3,127.0.0.4,127.0.0.5', 'extra': 'check-me']
output_dict = 'hosts': [d for host in input_dict['hosts'] for d in expand_dict(host)]

进一步分解,让我们用一个例子来试试。在这种情况下,我使用的是host = d['hosts'][2]

'hostname': 'ijk,uvw,xyz',
 'ip': '127.0.0.3,127.0.0.4,127.0.0.5',
 'extra': 'check-me'

kv_pairs = [[(k, v) for v in vals.split(",")] for k, vals in host.items()] 行为我们提供了内部项目列表的可能键值对列表。

[
    [('hostname', 'ijk'), ('hostname', 'uvw'), ('hostname', 'xyz')],
    [('ip', '127.0.0.3'), ('ip', '127.0.0.4'), ('ip', '127.0.0.5')],
    [('extra', 'check-me')],
]

如您所见,"hostname""ip" 键各有 3 个键值对,而 "extra" 键在原始主机字典中只有 1 个键值对。目标是生成 3 个字典,每个字典都带有 'extra': 'check-me'。所以,我们想找出我们期望生成的字典数量。

max_len = max(len(p) for p in kv_pairs) 行给了我们 3。然后,作为健全性检查,我们要确保 kv_pairs 中的每组键值对的长度为 1 或长度为 3。如果是其他, 问题不会很好定义,所以我们添加断言assert all(len(pairs) in 1, max_len for pairs in kv_pairs)

然后我们通过重复将所有长度为 1 kv 的对列表扩展为长度为 3。这个列表理解基本上采用所有长度为 3 的列表,并将长度为 1 的列表重复 3 次,因此它们的长度都相同。

updated_pairs = [p if len(p) == max_len else p * max_len for p in kv_pairs]

[[('hostname', 'ijk'), ('hostname', 'uvw'), ('hostname', 'xyz')],
 [('ip', '127.0.0.3'), ('ip', '127.0.0.4'), ('ip', '127.0.0.5')],
 [('extra', 'check-me'), ('extra', 'check-me'), ('extra', 'check-me')]]

现在一切都准备好了,我们可以开始创建字典了。我们可以为此使用zip(),它为我们提供了元组的迭代器,其中包含来自我们传入的每个输入迭代器的项目。我正在使用Python 的解包语法将updated_kv_pairs 中的每个列表扩展为zip() 的单独参数.换句话说,

zip(*updated_kv_pairs)

相同
zip(updated_kv_pairs[0], updated_kv_pairs[1], updated_kv_pairs[2])

zip() 的每次迭代都会为我们提供一个键值对列表,这些键值对位于我们输出的单个字典中。这给了我们

'hostname': 'ijk', 'ip': '127.0.0.3', 'extra': 'check-me'
'hostname': 'uvw', 'ip': '127.0.0.4', 'extra': 'check-me'
'hostname': 'xyz', 'ip': '127.0.0.5', 'extra': 'check-me'

【讨论】:

是的,我没有在我的代码中的任何地方使用 dict,它只是为了在这里进行解释。非常感谢您的及时回复。 @HardySandhu Weeeeeell 你试过了吗? ;-) @rchome 这个答案中的代码很棒,但旁边的文字解释会更好! 我也无法通过pythontutor.com 理解它。稍微解释一下会更好。 我已经用一些 cmets 更新了代码。让我知道是否有任何需要澄清的地方。

以上是关于创建单独的字典,其中包含值列表的主要内容,如果未能解决你的问题,请参考以下文章

从具有值列表的字典创建 Pyqt QtableWidget,然后返回字典

从字典列表创建DataFrame - 其中值是列表本身[重复]

在字典中显示列表值

Python - 从包含值列表的字典中添加具有映射值的新列

从字典列表中查找值,其中dicts具有不同数量的键

搜索特定值的嵌套字典列表[重复]