创建单独的字典,其中包含值列表
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,然后返回字典