Python: удалить повторяющиеся кортежи из списка, если они точно совпадают, включая порядок элементов
Я знаю, что подобные вопросы были заданы много раз в Stack Overflow, но мне нужно удалить дубликаты кортежей из списка, но не только, если их элементы совпадают, их элементы должны быть в одном порядке. Другими словами, (4,3,5)
и (3,4,5)
будут присутствовать на выходе, тогда как если бы были (3,3,5)
и (3,3,5)
, на выходе было бы только одно.
В частности, мой код:
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,2,2)
.
Ответы
Ответ 1
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)]
>>>
set
удалит только точные дубликаты.
Ответ 2
Вам нужны уникальные перестановки, а не комбинации:
y = list(set(itertools.permutations(x,3)))
То есть, (1,2,2) и (2,1,2) будут считаться одной и той же комбинацией, и только один из них будет возвращен. Они, однако, разные перестановки. Используйте set()
для удаления дубликатов.
Если впоследствии вы хотите отсортировать элементы в каждом кортеже, а также отсортировать весь список, вы можете сделать:
y = [tuple(sorted(q)) for q in y]
y.sort()
Ответ 3
Не нужно делать цикл for
, combinations
дает генератор.
x = [1,1,1,2,2,2,3,3,3,4,4,5]
y = list(set(itertools.combinations(x,3)))
Ответ 4
Это, вероятно, будет делать то, что вы хотите, но это огромный перебор. Это прототип низкого уровня для генератора, который может быть добавлен к itertools
в определенный день. Это низкий уровень, чтобы облегчить повторное внедрение его в 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)
Ответ 5
Ты был очень близок. Просто получайте перестановки, а не комбинации. Вопросы порядка в перестановках, и это не в комбинациях. Таким образом, (1, 2, 2) является отличной перестановкой из (2, 2, 1). Однако (1, 2, 2) считается сингулярной комбинацией одного 1 и двух 2s. Поэтому (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))
И вуаля, все готово.:)
Ответ 6
Использование 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)