优化迭代 2 个 IP 地址数据帧的三个嵌套 for 循环?
Optimize three nested for-loops iterating through 2 dataframes of IP addresses?
我有 2 个 CSV 文件。
一个带有主机名和 IP。
第二个带有 IP 信息(网络掩码、Cidr、子网名称等)
我目前的情况如下。
for i, ipAddress in CSV1:
for j, ipNetwork in CSV2:
if ipAddress in ipNetwork:
append ipNetwork['Subnet Name']
不幸的是,第一个 csv 有 9000 个 IP,第二个列表有 30'000 个子网。这需要花费大量时间来迭代。我知道这是一种糟糕的实施方式,但我知道我总能改进。
谁能告诉我如何更好地解决这个问题?我如何搜索和比较每个元素以缩短此脚本的运行时间?
这是示例数据
[CSV 1 - Sample IP]
IP Address
144.196.86.89
56.144.25.138
3.16.101.238
123.18.128.50
19.22.2.124
78.88.241.163
144.44.200.20
27.215.172.218
124.90.163.19
[CSV 2 - Sample Subnet Information]
address netmask Company Subnet Name Compartment Type cidr
10.2.1.0 255.255.255.0 UPS UPS Site 1 Desktop 10.2.1.0/24
10.2.2.0 255.255.255.0 UPS UPS Site 2 Desktop 10.2.2.0/24
10.2.3.0 255.255.255.0 UPS UPS Site 3 Desktop 10.2.3.0/24
10.2.4.0 255.255.255.0 UPS UPS Site 4 Desktop 10.2.4.0/24
10.2.5.0 255.255.255.0 UPS UPS Site 5 Desktop 10.2.5.0/24
10.2.6.0 255.255.255.0 UPS UPS Site 6 Desktop 10.2.6.0/24
10.2.7.0 255.255.255.0 UPS UPS Site 7 Desktop 10.2.7.0/24
10.2.8.0 255.255.255.0 UPS UPS Site 8 Desktop 10.2.8.0/24
10.2.10.0 255.255.254.0 UPS UPS Site 9 Desktop 10.2.10.0/23
10.2.12.0 255.255.255.0 UPS UPS Site 10 Desktop 10.2.12.0/24
10.2.13.0 255.255.255.0 UPS UPS Site 11 Desktop 10.2.13.0/24
1) 显然它很慢,因为 OP 具有 三个嵌套循环 :CSV1 文件上的两级嵌套迭代 (i, j),然后是 [=36 上的迭代=]ip网络。你应该避免像瘟疫一样的深度嵌套。
要测试 CSV1 中的成员资格,请对 CSV1 进行第一次迭代以读入所有 ip,并存储为 set
:
ips = [line[0] for line in CSV1.readlines()] # or whatever, using csv.reader
ips = set(ips)
事实上 Python 的最新版本允许您直接生成集合(这称为 生成器表达式 )
ips = set(line[0] for line in CSV1.readlines())
现在您根本不需要 j 迭代,因为您使用的是 set
。您只需使用 if ip in ...
测试会员资格
所以我们已经消除了你的三个嵌套循环之一。也许两个。
2) 此外 如果要在测试 ip in ipNetworks...
时获得性能提升,您可以使用正则表达式 and/or 分层 ipAddress
class,例如允许比较 ipAddress('157.55.130')
和 ipAddress('157.55.*.*)
。在比较 IP 时,请参阅 SO 上的许多现有重复项。您可以允许通配符 *
and/or xxx
。
如果您使用通配符并合并相邻地址,您应该能够分别将 CSV1 和 ipNetwork 长度压缩到 9K;30K 以下。
查看许多现有的 SO 问题,例如:
1. 使用正则表达式 Python: Efficient way to compare ip addresses in a csv file
1. 使用自定义 class Compare IP List to another IP List or IP Range
1. 比较范围
这里有一些很棒的建议,它们给了我很多值得关注的地方。
我最后做的是按 IP 对两个列表进行排序。一旦我比较了一个排序的 IP 列表并寻找它在 CIDR 列表中的 IP 网络,我就会将其设置为一个临时变量。许多 IP 是连续的,因此接下来的几个 IP 很可能也在临时中。
然后我基本上将搜索范围缩小到找到的 CIDR 的索引。所以每次迭代后,我的 CIDR 列表搜索都会减少。
它可能不漂亮或不是最优化的,但它确实有效。
等我稍加润色后,我会附上它的样本。
我有 2 个 CSV 文件。 一个带有主机名和 IP。 第二个带有 IP 信息(网络掩码、Cidr、子网名称等)
我目前的情况如下。
for i, ipAddress in CSV1:
for j, ipNetwork in CSV2:
if ipAddress in ipNetwork:
append ipNetwork['Subnet Name']
不幸的是,第一个 csv 有 9000 个 IP,第二个列表有 30'000 个子网。这需要花费大量时间来迭代。我知道这是一种糟糕的实施方式,但我知道我总能改进。
谁能告诉我如何更好地解决这个问题?我如何搜索和比较每个元素以缩短此脚本的运行时间?
这是示例数据
[CSV 1 - Sample IP]
IP Address
144.196.86.89
56.144.25.138
3.16.101.238
123.18.128.50
19.22.2.124
78.88.241.163
144.44.200.20
27.215.172.218
124.90.163.19
[CSV 2 - Sample Subnet Information]
address netmask Company Subnet Name Compartment Type cidr
10.2.1.0 255.255.255.0 UPS UPS Site 1 Desktop 10.2.1.0/24
10.2.2.0 255.255.255.0 UPS UPS Site 2 Desktop 10.2.2.0/24
10.2.3.0 255.255.255.0 UPS UPS Site 3 Desktop 10.2.3.0/24
10.2.4.0 255.255.255.0 UPS UPS Site 4 Desktop 10.2.4.0/24
10.2.5.0 255.255.255.0 UPS UPS Site 5 Desktop 10.2.5.0/24
10.2.6.0 255.255.255.0 UPS UPS Site 6 Desktop 10.2.6.0/24
10.2.7.0 255.255.255.0 UPS UPS Site 7 Desktop 10.2.7.0/24
10.2.8.0 255.255.255.0 UPS UPS Site 8 Desktop 10.2.8.0/24
10.2.10.0 255.255.254.0 UPS UPS Site 9 Desktop 10.2.10.0/23
10.2.12.0 255.255.255.0 UPS UPS Site 10 Desktop 10.2.12.0/24
10.2.13.0 255.255.255.0 UPS UPS Site 11 Desktop 10.2.13.0/24
1) 显然它很慢,因为 OP 具有 三个嵌套循环 :CSV1 文件上的两级嵌套迭代 (i, j),然后是 [=36 上的迭代=]ip网络。你应该避免像瘟疫一样的深度嵌套。
要测试 CSV1 中的成员资格,请对 CSV1 进行第一次迭代以读入所有 ip,并存储为 set
:
ips = [line[0] for line in CSV1.readlines()] # or whatever, using csv.reader
ips = set(ips)
事实上 Python 的最新版本允许您直接生成集合(这称为 生成器表达式 )
ips = set(line[0] for line in CSV1.readlines())
现在您根本不需要 j 迭代,因为您使用的是 set
。您只需使用 if ip in ...
测试会员资格
所以我们已经消除了你的三个嵌套循环之一。也许两个。
2) 此外 如果要在测试 ip in ipNetworks...
时获得性能提升,您可以使用正则表达式 and/or 分层 ipAddress
class,例如允许比较 ipAddress('157.55.130')
和 ipAddress('157.55.*.*)
。在比较 IP 时,请参阅 SO 上的许多现有重复项。您可以允许通配符 *
and/or xxx
。
如果您使用通配符并合并相邻地址,您应该能够分别将 CSV1 和 ipNetwork 长度压缩到 9K;30K 以下。
查看许多现有的 SO 问题,例如:
1. 使用正则表达式 Python: Efficient way to compare ip addresses in a csv file
1. 使用自定义 class Compare IP List to another IP List or IP Range
1. 比较范围
这里有一些很棒的建议,它们给了我很多值得关注的地方。
我最后做的是按 IP 对两个列表进行排序。一旦我比较了一个排序的 IP 列表并寻找它在 CIDR 列表中的 IP 网络,我就会将其设置为一个临时变量。许多 IP 是连续的,因此接下来的几个 IP 很可能也在临时中。
然后我基本上将搜索范围缩小到找到的 CIDR 的索引。所以每次迭代后,我的 CIDR 列表搜索都会减少。
它可能不漂亮或不是最优化的,但它确实有效。
等我稍加润色后,我会附上它的样本。