web-dev-qa-db-ja.com

重複するタプルが項目の順序を含めてまったく同じである場合は、リストから重複したタプルを削除します

Stack Overflowでこれに似た質問が何度も繰り返されることを知っていますが、重複するタプルをリストから削除する必要がありますが、要素が一致する場合だけでなく、要素は同じ順序である必要があります。言い換えると、 (4,3,5)および(3,4,5)は両方とも出力に存在しますが、両方がある場合は(3,3,5)および(3,3,5)、1つだけが出力されます。

具体的には、私のコードは:

import itertools

x = [1,1,1,2,2,2,3,3,3,4,4,5]
y = []

for x in itertools.combinations(x,3):
    y.append(x)
print(y)

このうち、出力はかなり長くなります。たとえば、出力では、両方の(1,2,1)および(1,1,2)。ただし、存在するのは1つだけです(1,2,2)

17
5813

set はそれを処理します:

>>> a = [(1,2,2), (2,2,1), (1,2,2), (4,3,5), (3,3,5), (3,3,5), (3,4,5)]
>>> set(a)
set([(1, 2, 2), (2, 2, 1), (3, 4, 5), (3, 3, 5), (4, 3, 5)])
>>> list(set(a))
[(1, 2, 2), (2, 2, 1), (3, 4, 5), (3, 3, 5), (4, 3, 5)]
>>>

setexactの重複のみを削除します。

33
user2555451

必要なのは、組み合わせではなく一意の順列です。

_y = list(set(itertools.permutations(x,3)))
_

つまり、(1,2,2)と(2,1,2)は同じ組み合わせと見なされ、そのうちの1つだけが返されます。ただし、それらは異なる順列です。重複を削除するには、set()を使用します。

その後、各タプル内の要素を並べ替え、リスト全体も並べ替えたい場合は、次のようにします。

_y = [Tuple(sorted(q)) for q in y]
y.sort()
_
2
sashkello

forループを実行する必要はありません。combinationsはジェネレーターを提供します。

x = [1,1,1,2,2,2,3,3,3,4,4,5]
y = list(set(itertools.combinations(x,3)))
1
xiaowl

これはおそらくあなたが望むことをするでしょうが、それは非常に過剰です。 mayitertoolsにいつか追加されるジェネレータの低レベルのプロトタイプです。 Cでの再実装を容易にするのは低レベルです。Nは反復可能な入力の長さで、最悪の場合のスペースO(N)を必要とし、最大でN*(N-1)//2要素を必要とします生成されるアナグラムの数に関係なく、比較。どちらも最適です;-)

次のように使用します。

>>> x = [1,1,1,2,2,2,3,3,3,4,4,5]
>>> for t in anagrams(x, 3):
...     print(t)
(1, 1, 1)
(1, 1, 2)
(1, 1, 3)
(1, 1, 4)
(1, 1, 5)
(1, 2, 1)
...

出力に重複はありません。注:これはPython 3コードです。Python 2.で実行するには、いくつかの変更が必要です。

import operator

class ENode:
    def __init__(self, initial_index=None):
        self.indices = [initial_index]
        self.current = 0
        self.prev = self.next = self

    def index(self):
        "Return current index."
        return self.indices[self.current]

    def unlink(self):
        "Remove self from list."
        self.prev.next = self.next
        self.next.prev = self.prev

    def insert_after(self, x):
        "Insert node x after self."
        x.prev = self
        x.next = self.next
        self.next.prev = x
        self.next = x

    def advance(self):
        """Advance the current index.

        If we're already at the end, remove self from list.

        .restore() undoes everything .advance() did."""

        assert self.current < len(self.indices)
        self.current += 1
        if self.current == len(self.indices):
            self.unlink()

    def restore(self):
        "Undo what .advance() did."
        assert self.current <= len(self.indices)
        if self.current == len(self.indices):
            self.prev.insert_after(self)
        self.current -= 1

def build_equivalence_classes(items, equal):
    ehead = ENode()
    for i, elt in enumerate(items):
        e = ehead.next
        while e is not ehead:
            if equal(elt, items[e.indices[0]]):
                # Add (index of) elt to this equivalence class.
                e.indices.append(i)
                break
            e = e.next
        else:
            # elt not equal to anything seen so far:  append
            # new equivalence class.
            e = ENode(i)
            ehead.prev.insert_after(e)
    return ehead

def anagrams(iterable, count=None, equal=operator.__eq__):
    def perm(i):
        if i:
            e = ehead.next
            assert e is not ehead
            while e is not ehead:
                result[count - i] = e.index()
                e.advance()
                yield from perm(i-1)
                e.restore()
                e = e.next
        else:
            yield Tuple(items[j] for j in result)

    items = Tuple(iterable)
    if count is None:
        count = len(items)
    if count > len(items):
        return

    ehead = build_equivalence_classes(items, equal)
    result = [None] * count
    yield from perm(count)
1
Tim Peters

あなたは本当に親しかった。組み合わせではなく順列を取得するだけです。順序は順列で重要であり、組み合わせではありません。したがって、(1、2、2)は(2、2、1)とは異なる順列です。ただし、(1、2、2)は、1 1と2 2の1つの組み合わせと見なされます。したがって、(2、2、1)は(1、2、2)とは異なる組み合わせとは見なされません。

リストyをセットに変換して、重複を削除することができます...

import itertools

x = [1,1,1,2,2,2,3,3,3,4,4,5]
y = []

for x in itertools.permutations(x,3):
    y.append(x)
print(set(y))

これで出来上がりです。 :)

1
Shashank

set の使用はおそらく機能するはずです。セットは基本的に、重複する要素を含まないコンテナです。

Pythonには、セットのデータ型も含まれています。セットは、重複する要素がない順序付けられていないコレクションです。基本的な用途には、メンバーシップテストや重複エントリの排除が含まれます。セットオブジェクトは、ユニオン、インターセクション、差分、対称差分などの数学演算もサポートしています。

import itertools

x = [1,1,1,2,2,2,3,3,3,4,4,5]
y = set()

for x in itertools.combinations(x,3):
    y.add(x)
print(y)
0
TankorSmash