gpt4 book ai didi

python-3.x - 加快 for 循环迭代两个大(10000s)列表的速度

转载 作者:行者123 更新时间:2023-12-03 08:30:42 25 4
gpt4 key购买 nike

我正在尝试将一个 IP 地址列表与它可能所属的另一网络列表进行检查。长度:

len(IP_addresses_list) = 31995
len(Network_list) = 54099

big_dict = {}
for ip in IP_addresses_list:
address_and_networks = self.is_subnet_of(ip, Network_list)
big_dict.update(address_and_networks)

df = pd.DataFrame.from_dict(big_dict, orient="index")

循环通过以下方式验证它是否属于网络:

def is_subnet_of(self, ip, Network_list):
address_and_networks = {}
address = ipaddress.ip_address(ip)
for net in Network_list:
network = ipaddress.ip_network(net)
res = network.supernet_of(ipaddress.ip_network(f"{address}/{address.max_prefixlen}"))
if res:
if ip in address_and_networks:
address_and_networks[ip].append(net)
else:
address_and_networks[ip] = [net]

return address_and_networks

address_and_networks 字典可能如下所示:

{
"xxx.xxx.xxx.xxx": ["xxx.xxx.xxx.xxx/24", "xxx.xxx.xxx.xxx/23"],
"yyy.yyy.yyy.yyy": ["yyy.yyy.yyy.yyy/24", "yyy.yyy.yyy.yyy/23"]
}

目前这种方法非常慢,慢到根本无法使用。我想以某种方式加速这一过程,也许可以通过将原始列表(IP_addresses_list,Network_list)转储到数据帧中,然后通过应用 is_subnet_of 对数据帧执行一些全面的执行方法(可能类似于 dataframe.selectdataframe.apply)。知道如何加快速度吗?

编辑

我进一步简化了代码,但我仍然采用循环数据帧:

    df = pd.DataFrame({"IP_Address": ip_s.map(ipaddress.ip_address),
"Network": net_s.map(ipaddress.ip_network),
"Associated": np.nan})

for i, address in df["IP_Address"].iteritems():
if address != address:
continue
net_list = []
for j, network in df["Network"].iteritems():
if network.supernet_of(ipaddress.ip_network(f"{address}/{address.max_prefixlen}")):
net_list.append(str(network))
df.loc[i, "Associated"] = net_list

示例数据:

Addresses = ['172.16.56.40','172.16.16.16']

Networks = ['172.16.56.0/24', '172.16.56.32/27']

最佳答案

位操作将使速度更快,它还允许一些昂贵的操作仅执行一次。

考虑以下函数:

def is_subnet_of(ip: str, network: str) -> bool:
def bin_ip(ip: str) -> int:
return int("".join(map(lambda n: bin(int(n)).replace("0b", "").zfill(8), ip.split("."))), 2)

net, mask_len = network.split("/")
mask_len = int(mask_len)

# Convert ip and net to binary-format
ip_bin = bin_ip(ip)
net_bin = bin_ip(net)

# Build mask
mask = int(mask_len * '1' + (32 - mask_len) * '0', 2)

# check (Bit operations are faster)
return net_bin ^ (mask & ip_bin) == 0

# `is_subnet_of("172.16.56.40", "172.16.56.0/24")` will return True.

需要 3 个步骤才能确定给定的 ip 是否在网络中:

  1. 将 ip 和 net 转换为二进制格式(我们需要另一个函数bin_ip来完成这项工作)
  2. 构建网络掩码
  3. 检查:(net ^ (mask & ip))

更好的是,步骤 1 和步骤 2 只需执行一次,这将节省我们大部分时间:

from typing import Tuple


def check_subnet(ip, network_list):
def bin_ip(ip: str) -> int:
return int(
"".join(map(lambda n: bin(int(n)).replace("0b", "").zfill(8), ip.split("."))), 2
)

def bin_net(net: str) -> Tuple[int, int]:
net_ip, mask_len = net.split("/")
mask_len = int(mask_len)

net_bin = bin_ip(net_ip)
mask = int(mask_len * "1" + (32 - mask_len) * "0", 2)

return net_bin, mask

def is_subnet_of(ip: int, network: Tuple[int, int]) -> bool:
return network[0] ^ (network[1] & ip) == 0

ip = bin_ip(ip)
networks = tuple(map(bin_net, network_list))

return tuple(is_subnet_of(ip, network) for network in networks)


# Below are the test section
address_and_networks = {"172.16.56.40": ["172.16.56.0/24", "172.16.56.32/27"]}

result = tuple(check_subnet(ip, network_list) for ip, network_list in address_and_networks.items())

print(result)

如果你坚持使用pandas矢量化操作,那么我建议:

  1. 使用我上面提到的bin_ip函数来构造ip、网络和掩码的矩阵(这一步的复杂度为O(n))
  2. 使用numpy矩阵运算(众所周知,pandas实际上是使用numpy来完成数值计算)计算结果:result = ((ip & mask) == net.T)<

这样,我们将自己完成 O(n) 复杂度,并将 O(n^2) 部分留给 pandas/numpy 向量化操作。

关于python-3.x - 加快 for 循环迭代两个大(10000s)列表的速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65218979/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com