我有一个庞大的网络列表(称为A),我需要检查这些网络的地址是否存在于另一个网络列表中(称为B):
两个列表的格式如下:
听A
1.2.3.4
145.2.3.0/24
6.5.0.0/16
3.4.1.0/24
听B
1.5.6.7
10.0.3.0/24
1.2.3.0/24
3.4.0.0/16
两个列表A∩B:etc
的交集的预期结果1.2.3.4
3.4.1.0/24
我的第一次测试很天真:
此方法适用于小型列表。但是,此解决方案不适用于数千个网络(即数百万个IP地址),因为我don't have enough memory。此外,此解决方案不适用于 IPv6 网络。
执行两个列表交集的最有效方法是什么?
另外:我还要在列表A和其他列表之间重复这个:B:A∩C,A∩D等。
我对所有建议持开放态度,即使使用pig: - )
解决方案:
def chunks(l, n):
for i in xrange(0, len(l), n):
yield l[i:i+n]
res = []
for chunk_a in chunks(A, 1000):
for chunk_b in chunks(B, 1000):
C = IPSet(chunk_a) & IPSet(chunk_b)
if C > IPSet([]):
res.append(C)
答案 0 :(得分:1)
这是基于实现IP地址/网络集的netaddr
包的一种可能性。
首先,考虑如果A =A1∪A2和B =B1∪B2,那么A∩B=(A1∩B1)∪(A1∩B2)∪(A2∩B1)∪(A2∩B2)。 / p>
因此,您将列表分成小集并使用上面的内容逐步计算交集。例如:
from netaddr import IPSet
A1 = IPSet(['1.2.3.4','145.2.3.0/24'])
A2 = IPSet(['6.5.0.0/16','3.4.1.0/24'])
B1 = IPSet(['1.5.6.7','10.0.3.0/24'])
B2 = IPSet(['1.2.3.0/24','3.4.0.0/16'])
A1B1 = A1 & B1
A1B2 = A1 & B2
A2B1 = A2 & B1
A2B2 = A2 & B2
A1B1 | A1B2 | A2B1 | A2B2
-> IPSet(['1.2.3.4/32', '3.4.1.0/24'])
但考虑到这一点,在使用IPSet时,您不需要列出所有地址,您可以执行交叉点而无需将列表拆分为小集。
更新:在具有4GB内存的笔记本电脑上,两个5,000个随机定义的网络列表(长度为8到24位)的交集仅需几秒钟:
制作两个IP地址列表:
import random
f = open('iplist1.txt','w')
for i in range(5000):
ip = '.'.join([str(random.randint(1,254)) for i in range(4)])
ip += '/'+str(random.randint(8,24))
f.write(ip+'\n')
f.close()
f = open('iplist2.txt','w')
for i in range(5000):
ip = '.'.join([str(random.randint(1,254)) for i in range(4)])
ip += '/'+str(random.randint(8,24))
f.write(ip+'\n')
f.close()
将它们相交:
import time
import netaddr
ipset1 = netaddr.IPSet(open('iplist1.txt','r').readlines())
ipset2 = netaddr.IPSet(open('iplist2.txt','r').readlines())
print "Set 1:", len(ipset1), "IP addresses"
print "Set 2:", len(ipset2), "IP addresses"
start = time.time()
ipset = ipset1 & ipset2
print "Elapsed:", time.time() - start
print "Intersection:",len(ipset),"IP addresses"
答案 1 :(得分:0)
如果你对猪开放,那么没有什么比这更容易了。内存耗尽不会有麻烦,JOIN
:
A = LOAD '/path/to/A' AS (ip:chararray);
B = LOAD '/path/to/B' AS (ip:chararray);
intersection = FOREACH (JOIN A BY ip, B BY ip) GENERATE A::ip;
STORE intersection INTO '/path/to/output';
完成。