【问题标题】:How can I add multiple values of duplicate keys to a dictionary?如何将重复键的多个值添加到字典中?
【发布时间】:2022-01-18 12:49:39
【问题描述】:

我有这个字典列表,我想将端口值设为主键,因为该端口在列表中的许多字典中都是相同的。

代码:

def vrni_recommended_rules(json_output):
    response_dict = []
    ports = []
    source_ip = []
    for i in json_output['results']:
        ports.append(i['json']['port']['display'])
        response_dict.append(dict(
            source_ip = i['json']['source_ip']['ip_address'],
            destination_ip = i['json']['destination_ip']['ip_address'],
            protcol = i['json']['protocol'].lower(),
            traffic_type = i['json']['traffic_type'].lower(),
            iana_name = i['json']['port']['iana_name'],
            port = i['json']['port']['display'],
            firewall_action = i['json']['firewall_action'].lower(),
            protocol_number = i['json']['protocol'].replace('UDP', '17').replace('TCP', '6')
            ))


    return response_dict

我收到以下回复:

"results": [
        {
            "destination_ip": "199.7.7.7",
            "firewall_action": "allow",
            "iana_name": "https",
            "port": "443",
            "protcol": "tcp",
            "protocol_number": "6",
            "source_ip": "192.30.6.250",
            "traffic_type": "internet_traffic"
        },
        {
            "destination_ip": "15.225.50.14",
            "firewall_action": "allow",
            "iana_name": "https",
            "port": "443",
            "protcol": "tcp",
            "protocol_number": "6",
            "source_ip": "192.30.6.250",
            "traffic_type": "internet_traffic"
        },
        {
            "destination_ip": "96.6.6.6",
            "firewall_action": "allow",
            "iana_name": "https",
            "port": "443",
            "protcol": "tcp",
            "protocol_number": "6",
            "source_ip": "192.30.6.250",
            "traffic_type": "internet_traffic"
        },
        {
            "destination_ip": "192.155.2.199",
            "firewall_action": "allow",
            "iana_name": "dns",
            "port": "53",
            "protcol": "udp",
            "protocol_number": "17",
            "source_ip": "192.30.6.250",
            "traffic_type": "east_west_traffic"
        },
        {
            "destination_ip": "30.22.239.107",
            "firewall_action": "allow",
            "iana_name": "https",
            "port": "443",
            "protcol": "tcp",
            "protocol_number": "6",
            "source_ip": "192.30.6.250",
            "traffic_type": "internet_traffic"
        },
        {
            "destination_ip": "55.55.55.55",
            "firewall_action": "allow",
            "iana_name": "https",
            "port": "443",
            "protcol": "tcp",
            "protocol_number": "6",
            "source_ip": "192.30.6.250",
            "traffic_type": "internet_traffic"
        },
        {
            "destination_ip": "66.66.66.66",
            "firewall_action": "allow",
            "iana_name": "https",
            "port": "443",
            "protcol": "tcp",
            "protocol_number": "6",
            "source_ip": "192.30.6.250",
            "traffic_type": "internet_traffic"
        },
        {
            "destination_ip": "192.192.192.125",
            "firewall_action": "allow",
            "iana_name": "ldaps",
            "port": "636",
            "protcol": "tcp",
            "protocol_number": "6",
            "source_ip": "192.30.6.250",
            "traffic_type": "east_west_traffic"
        },
        {
            "destination_ip": "192.192.192.192",
            "firewall_action": "allow",
            "iana_name": "ntp",
            "port": "123",
            "protcol": "udp",
            "protocol_number": "17",
            "source_ip": "192.30.0.1",
            "traffic_type": "east_west_traffic"
        },
        {
            "destination_ip": "99.99.99.99",
            "firewall_action": "allow",
            "iana_name": "https",
            "port": "443",
            "protcol": "tcp",
            "protocol_number": "6",
            "source_ip": "192.30.6.250",
            "traffic_type": "internet_traffic"
        }
    ]
}

如果我以端口作为主键来压缩字典,它显然会删除重复项。

如果我添加:

    d = dict(zip(ports, response_dict))

    return d

我明白了:

    "results": {
        "123": {
            "destination_ip": 192.30.30.30",
            "firewall_action": "allow",
            "iana_name": "ntp",
            "port": "123",
            "protcol": "udp",
            "protocol_number": "17",
            "source_ip": 192.30.0.1",
            "traffic_type": "east_west_traffic"
        },
        "443": {
            "destination_ip": "52.52.52.52",
            "firewall_action": "allow",
            "iana_name": "https",
            "port": "443",
            "protcol": "tcp",
            "protocol_number": "6",
            "source_ip": 192.30.6.250",
            "traffic_type": "internet_traffic"
        },
        "53": {
            "destination_ip": 192.2.2.2",
            "firewall_action": "allow",
            "iana_name": "dns",
            "port": "53",
            "protcol": "udp",
            "protocol_number": "17",
            "source_ip": 192.30.6.2",
            "traffic_type": "east_west_traffic"
        },
        "636": {
            "destination_ip": 192.30.30.30",
            "firewall_action": "allow",
            "iana_name": "ldaps",
            "port": "636",
            "protcol": "tcp",
            "protocol_number": "6",
            "source_ip": 192.30.6.6",
            "traffic_type": "east_west_traffic"
        }
    }
}

这几乎是我想要的,但是我想确保如果有多个字典带有端口 443 或其他端口,它会显示在主端口键下...

我想要它...

        "443": {
            "destination_ip": ["52.52.52.52", "53.53.53.53", "54.54.54.54"],
            "firewall_action": "allow",
            "iana_name": "https",
            "port": "443",
            "protcol": "tcp",
            "protocol_number": "6",
            "source_ip": ["192.30.6.250", "192.168.30.30", "192.6.6.6"],
            "traffic_type": "internet_traffic"
            }

【问题讨论】:

  • 我认为你是在找麻烦。例如,如果您有端口 53 (dns) 的规则,那么您可能同时有 udp 和 tcp 的规则。也许一个被允许,另一个被丢弃。我认为您应该重新考虑最终的 dict 格式(“我想要它的方式”)以确保它是合适的。
  • 这是一个公平的问题!

标签: python list dictionary zip


【解决方案1】:

对于您期望的输出,我认为您可以执行以下操作:

def vrni_recommended_rules(json_output):
    response_dict = {}
    for i in json_output["results"]:
        port = i["json"]["port"]["display"]
        try:
            port_dict = response_dict[port]
        except KeyError:
            response_dict[port] = dict(
                source_ip=[i["json"]["source_ip"]["ip_address"]],
                destination_ip=[i["json"]["destination_ip"]["ip_address"]],
                protcol=i["json"]["protocol"].lower(),
                traffic_type=i["json"]["traffic_type"].lower(),
                iana_name=i["json"]["port"]["iana_name"],
                port=i["json"]["port"]["display"],
                firewall_action=i["json"]["firewall_action"].lower(),
                protocol_number=i["json"]["protocol"].replace("UDP", "17").replace("TCP", "6"),
            )
        else:
            port_dict["destination_ip"].append(i["json"]["destination_ip"]["ip_address"])
            port_dict["source_ip"].append(i["json"]["source_ip"]["ip_address"])

    return response_dict

顺便说一句,我无法运行它,因为你没有提供 .json,所以我没有测试这段代码。

【讨论】:

  • 这符合我的要求,我只需要解决两个问题。 @vaizki 提到的一个和一个具有源 IP 的。由于源 IP 很多时候都是相同的,我最终会在列表中得到重复,但我想我可以在代码中稍后处理。
  • 我明白了。要修复源 IP 的重复性,您可以简单地将列表结构替换为一组,因此将 append 方法替换为 add 方法。这样源 IP 将自动摆脱重复的 IP。要解决@vaizki 提到的问题,您可以将协议及其规则收集到一个嵌套字典中,其中协议作为键,相关规则作为值。如果与给定协议关联的规则不仅仅涉及防火墙操作,则该值可能是您选择的另一种数据结构。如果不清楚,我可以给你一个实现。
猜你喜欢
  • 2023-03-31
  • 2017-01-04
  • 2014-04-13
  • 1970-01-01
  • 1970-01-01
  • 2014-01-02
  • 1970-01-01
  • 2015-02-16
相关资源
最近更新 更多