2

私は、長さが異なる両方の次元の数値の2次元リストを持っています。これらは、ホストの開いているポートを表します。以下は、4 つの異なるホストで開いているポートを示すリストです。

ports = [[22,23],[22],[22,23,80],[23,80]]

2 つ以上のホストで共有されているポートの一意の組み合わせをすべて数えたいと思います。この例では、次の結果が得られるはずです。

Ports -> Count
22     -> 3
22, 23 -> 2
23     -> 3
23, 80 -> 2
80     -> 2

ソリューションを実装しましたが、特定の組み合わせのカウントが使用しているホストの数を超える傾向があるため、結果は正しくありません。簡潔にするために、非常に長いソリューションを投稿していませんが、擬似コードで概説します:

  • 各ホスト間の交点のマトリックスを作成する

  • マトリックスを抽出/平坦化して、一意のセットのみを含めます。つまり、逆順ではありません。

    -- a AND b, b AND a => a AND b
    
  • (抽出/平坦化) リストからのポートの一意の各セットと、そのセットが発生した回数を含む新しいリストを作成します。
4

1 に答える 1

5

itertoolspowersetレシピを使用:

from collections import Counter
from itertools import chain, combinations

def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

def port_table(ports):
    d = Counter()
    for portseq in ports:
        for subset in powerset(sorted(portseq)):
            if subset:
                d[subset] += 1
    return d

基本的に、powersetインクリメント可能なすべてのサブセットを指定し (空のものを含むため、if subset:スキップする必要があります)、ポートの各リストに表示されるサブセットごとに、Counterオブジェクトをインクリメントします。これにより、

>>> ports = [[22,23],[22],[22,23,80],[23,80]]
>>> table = port_table(ports)
>>> for port, count in sorted(table.items()):
...     if count > 1:
...         print port, '->', count
... 
(22,) -> 3
(22, 23) -> 2
(23,) -> 3
(23, 80) -> 2
(80,) -> 2
于 2012-10-05T12:39:06.150 に答える