0

ネットワークの膨大なリスト (A と呼ばれる) があり、これらのネットワークのアドレスが別のネットワーク リスト (B と呼ばれる) に存在するかどうかを確認する必要があります。

2 つのリストの形式は次のとおりです。

リスト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

2 つのリストの交差の期待される結果 A ∩ B: など

1.2.3.4
3.4.1.0/24

私の最初のテストは素朴でした:

この方法は小さなリストで機能します。ただし、このソリューションは、十分なメモリがないため、何千ものネットワーク (つまり、数百万の IP アドレス) には適していません。さらに、このソリューションはIPv6ネットワークには適していません。

2 つのリストを交差させる最も効果的な方法は何ですか?

追加: リスト A と他のリストの間でこれを繰り返さなければなりません。 B : A ∩ C、A ∩ D など。

でも、私はすべての提案を受け入れます:-)

解決 :

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)
4

2 に答える 2

1

netaddrIP アドレス/ネットワーク セットを実装するパッケージに基づく 1 つの可能性を次に示します。

まず、A = A1 ∪ A2 かつ B = B1 ∪ B2 とすると、A ∩ B = (A1 ∩ B1) ∪ (A1 ∩ B2) ∪ (A2 ∩ B1) ∪ (A2 ∩ B2) となります。

したがって、リストを小さなセットに分割し、上記を使用して交差を段階的に計算します。例えば:

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 を使用する場合、すべてのアドレスをリストする必要がないことを考慮すると、リストを小さなセットに分割することに頼ることなく交差を実行できる場合があります。


更新: 5,000 のランダムに定義されたネットワーク (長さ 8 ~ 24 ビット) の 2 つのリストの交差は、4 GB のメモリを搭載したラップトップで数秒しかかかりません。

IP アドレスの 2 つのリストを作成します。

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"
于 2013-03-23T14:36:54.333 に答える
0

もしあなたがPigにオープンであるなら、これ以上簡単なことはありません。メモリ不足の問題はなく、交差点は次のように簡単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';

終わり。

于 2013-03-24T04:35:49.947 に答える