我知道类似的问题在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)
。
答案 0 :(得分:30)
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
只会删除完全重复项。
答案 1 :(得分: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()
答案 2 :(得分:1)
无需执行for
循环,combinations
会生成一个生成器。
x = [1,1,1,2,2,2,3,3,3,4,4,5]
y = list(set(itertools.combinations(x,3)))
答案 3 :(得分:1)
这可能会做你想要的,但这是一个巨大的矫枉过正。这是一个生成器的低级原型,有一天可能被添加到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)
答案 4 :(得分:1)
你真的很亲密。只是得到排列,而不是组合。排列中的顺序很重要,它不是组合的。因此,(1,2,2)是与(2,2,1)不同的排列。然而,(1,2,2)被认为是1和2 2的单一组合。因此,(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))
瞧,你已经完成了。 :)
答案 5 :(得分:0)
使用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)