1

昨日質問しましたが、Tim Peters のおかげで解決しました。問題はここにあります。

itertools.product 繰り返し要素を削除する

新しい質問はこれのさらなるバージョンです。今回はタプルの中にタプルを生成します。以下に例を示します。

lis = [[(1,2), (3,4)], [(5,2), (1,2)], [(2,1), (1,2)]]

itertools.product 関数で使用すると、次のようになります。

((1, 2), (5, 2), (2, 1))
((1, 2), (5, 2), (1, 2))
((1, 2), (1, 2), (2, 1))
((1, 2), (1, 2), (1, 2))
((3, 4), (5, 2), (2, 1))
((3, 4), (5, 2), (1, 2))
((3, 4), (1, 2), (2, 1))
((3, 4), (1, 2), (1, 2))

シーケンスに (a,b) が含まれている場合、(b,a) を含むことができないように変更したいと考えています。この例では、このシーケンスを見ると、((3, 4), (1, 2), (2, 1))内部に (1,2) と (2,1) があります。したがって、このシーケンス((3, 4), (1, 2), (2, 1))は結果で考慮されるべきではありません。

私が言ったように、以前に同様の質問をしましたが、その場合、要素の重複は考慮されていませんでした。私はそれを私の問題に適応させようとします。ここに変更されたコードがあります。旧バージョンでの変更箇所はコメントにて承っております。

def reverse_seq(seq):
    s = []
    for i in range(len(seq)):
        s.append(seq[-i-1])         
    return tuple(s)


def uprod(*seqs):  
    def inner(i):
        if i == n:
            yield tuple(result)
            return
        for elt in sets[i] - reverse:
            #seen.add(elt)
            rvrs = reverse_seq(elt)
            reverse.add(rvrs)
            result[i] = elt
            for t in inner(i+1):
                yield t
            #seen.remove(elt)
            reverse.remove(rvrs)

    sets = [set(seq) for seq in seqs]
    n = len(sets)
    #seen = set()
    reverse = set()
    result = [None] * n
    for t in inner(0):
        yield t

私の意見では、このコードは機能するはずですが、入力でエラーが発生していますlis = [[(1,2), (3,4)], [(5,2), (1,2)], [(2,1), (1,2)]]。どこが間違っているのか理解できませんでした。

for i in uprod(*lis):
    print i

出力は、

((1, 2), (1, 2), (1, 2))
Traceback (most recent call last):
  File "D:\Users\SUUSER\workspace tree\sequence_covering _array\denemeler_buraya.py", line 39, in <module>
    for i in uprod(*lis):
  File "D:\Users\SUUSER\workspace tree\sequence_covering _array\denemeler_buraya.py", line 32, in uprod
    for t in inner(0):
  File "D:\Users\SUUSER\workspace tree\sequence_covering _array\denemeler_buraya.py", line 22, in inner
    for t in inner(i+1):
  File "D:\Users\SUUSER\workspace tree\sequence_covering _array\denemeler_buraya.py", line 25, in inner
    reverse.remove(rvrs)
KeyError: (2, 1)

ありがとう、

4

2 に答える 2

1

セットを使用して、順序が不要な順序を取り除きます。実際にfrozensetを使用しているので、簡単にネストできます。

タプルの番号の順序は無視する必要があるため、最初にlisを (凍結された) セットのリストのリストに変換します。

>>> lis = [[(1,2), (3,4)], [(5,2), (1,2)], [(2,1), (1,2)]]
>>> lis_ = [[frozenset(x) for x in y] for y in lis]

次に、製品を作成し、結果をセットに入れて、重複を取り除きます。

>>> result = set(x for x in itertools.product(*lis_))
>>> result
{(frozenset({3, 4}), frozenset({1, 2}), frozenset({1, 2})), (frozenset({1, 2}), frozenset({1, 2}), frozenset({1, 2})), (frozenset({3, 4}), frozenset({2, 5}), frozenset({1, 2})), (frozenset({1, 2}), frozenset({2, 5}), frozenset({1, 2}))}

そして、私たちはすでに終わっています。それらを今すぐ印刷して、少しきれいにすると(frozenset()出力の一部を取り除くと、結果が得られます:

>>> for r in result:
        print([tuple(x) for x in r])

[(3, 4), (1, 2), (1, 2)]
[(1, 2), (1, 2), (1, 2)]
[(3, 4), (2, 5), (1, 2)]
[(1, 2), (2, 5), (1, 2)]

からの結果をフィルタリングするだけの別のソリューションitertools.product

>>> lis = [[(1,2), (3,4)], [(5,2), (1,2)], [(2,1), (1,2)]]
>>> seenProducts = set()
>>> for p in itertools.product(*lis):
        product = tuple(frozenset(x) for x in p)
        if product not in seenProducts:
            seenProducts.add(product)
            print(p) # print original product

((1, 2), (5, 2), (2, 1))
((1, 2), (1, 2), (2, 1))
((3, 4), (5, 2), (2, 1))
((3, 4), (1, 2), (2, 1))
于 2013-11-03T15:39:53.333 に答える