python-3.x - 使用其中的值列表创建单独的字典

标签 python-3.x dictionary data-structures key-value

我有这样一本字典:

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'}
    ]
}

这意味着在给定值列表的任何地方,每个值列表都应该有一个单独的子字典。

最佳答案

也许是这样的?

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 个键值对, 只有 1 对原始主机字典中的“extra” 键。目标是生成 3 个字典,每个字典中都有 'extra': 'check-me'。因此,我们想要找到我们期望生成的词典数量。

max_len = max(len(p) for p in kv_pairs) 给我们 3。然后,就像完整性检查一样,我们要确保每组键值对in kv_pairs 要么是长度 1,要么是长度 3。如果是其他任何东西,问题就不好定义,所以我们添加断言 assert all(len(pairs) in {1, max_len} 对于 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'}

关于python-3.x - 使用其中的值列表创建单独的字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70419187/

相关文章:

python - 内隐微分 Sympy

c# - 根据键对字典列表进行排序

python - 如何按字典键内的值对字典进行排序?

c++ - 解码无符号短值的函数

data-structures - 线程二叉树的问题

python - python 对包含字符串和整数的列表中的元素求和,并将答案放入另一个列表中

python-3.x - 在使用 dictconfig 的 python3 日志记录设置中记录异常时如何格式化错误消息和堆栈?

python - 读取 txt 文件并将各个列保存为列表

android - fragment 中的 MapView 为空

arrays - 如何在 Perl 中按列对数组或表进行排序?