【问题标题】:Creating cartesian product of sub-dictionary key-val pairs创建子字典键值对的笛卡尔积
【发布时间】:2022-01-24 21:26:58
【问题描述】:

我有这本词典:

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

我想要一个字典,其中包含键值对的笛卡尔积。

我需要从中创建以下字典:

d = {
    'hosts': [
        {'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'},
        {'hostname': 'abc', 'ip': '127.0.0.1', 'extra': 'check-for'},
        {'hostname': 'abc', 'ip': '127.0.0.1', 'extra': 'check-this'}
        {'hostname': 'def', 'ip': '127.0.0.2', 'extra': 'check-for'},
        {'hostname': 'def', 'ip': '127.0.0.2', 'extra': 'check-this'}
    ]
}

【问题讨论】:

  • 您的示例不包含三个字段之间的所有可能组合,因为每个主机名都对应一个 IP。所以它实际上不是笛卡尔积。
  • 我的要求是只有每个主机名应该有后续的IP,但“额外”应该在所有三个主机名和IP中都有

标签: python python-3.x data-structures cartesian-product


【解决方案1】:

提取所有可能的值后,您可以使用itertools.product将它们组合起来:

for host in d['hosts']:
    hostnames.extend(host['hostname'].split(','))
    ips.extend(host['ip'].split(','))
    extras.extend(host['extra'].split(','))

result = {'hosts': []}
for (hostname, ip, extra) in product(hostnames, ips, extras):
    result['hosts'].append({'hostname': hostname, 'ip': ip, 'extra': extra})

这会产生一个笛卡尔积,但这意味着您还可以获得主机名和 IP 之间的所有组合。所以你必须跟踪主机名 -> IP 映射:

result = {'hosts': []}
for host in d['hosts']:
    hostnames = host['hostname'].split(',')
    ips = host['ip'].split(',')
    host2ip = {hostname: ip for hostname, ip in zip(hostnames, ips)}
    extras = host['extra'].split(',')

    for (hostname, extra) in product(hostnames, extras):
        result['hosts'].append({'hostname': hostname, 'ip': host2ip[hostname], 'extra': extra})

这给了

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

【讨论】:

  • 解决方案是正确的,但实际上主机名在字典列表中采用了其他字典“额外”的产品。我通过提供示例来稍微编辑我的问题。请帮忙。
  • @HardySandhu 我已经更新了我的答案
  • 它成功了,我能够得到所需的输出@JanWilamowski
【解决方案2】:

一种方法:

from itertools import product, chain


def f(d):
    t = product(zip(*(z := [d[k].split(',') for k in d])[:2]), z[2])
    return [dict(zip(d, (*x, y))) for x, y in t]

{'hosts': [*chain(*map(f, d['hosts']))]}

输出:

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

【讨论】:

  • 这仅打印字典列表中的 1 个字典。我在这里做错了吗?
猜你喜欢
  • 2019-02-10
  • 2017-10-16
  • 1970-01-01
  • 2011-07-10
  • 1970-01-01
  • 2023-03-17
  • 2018-11-09
  • 2017-08-24
  • 1970-01-01
相关资源
最近更新 更多