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