itertools.product 消除重复元素
Posted
技术标签:
【中文标题】itertools.product 消除重复元素【英文标题】:itertools.product eliminating repeated elements 【发布时间】:2013-11-02 17:10:18 【问题描述】:当我使用itertools.product
时,如何跳过迭代中具有重复元素的元组?或者比方说,无论如何不要在迭代中查看它们?因为如果列表数量太多,跳过可能会很耗时。
Example,
lis1 = [1,2]
lis2 = [2,4]
lis3 = [5,6]
[i for i in product(lis1,lis2,lis3)] should be [(1,2,5), (1,2,6), (1,4,5), (1,4,6), (2,4,5), (2,4,6)]
它不会有(2,2,5)
和(2,2,6)
,因为这里的 2 是重复的。我该怎么做?
【问题讨论】:
【参考方案1】:itertools
通常作用于输入中唯一的位置,而不是唯一的值。因此,当您想要删除重复值时,您通常必须对itertools
结果序列进行后处理,或者“滚动您自己的”。因为在这种情况下后处理可能非常低效,所以自己动手吧:
def uprod(*seqs):
def inner(i):
if i == n:
yield tuple(result)
return
for elt in sets[i] - seen:
seen.add(elt)
result[i] = elt
for t in inner(i+1):
yield t
seen.remove(elt)
sets = [set(seq) for seq in seqs]
n = len(sets)
seen = set()
result = [None] * n
for t in inner(0):
yield t
然后,例如,
>>> print list(uprod([1, 2, 1], [2, 4, 4], [5, 6, 5]))
[(1, 2, 5), (1, 2, 6), (1, 4, 5), (1, 4, 6), (2, 4, 5), (2, 4, 6)]
>>> print list(uprod([1], [1, 2], [1, 2, 4], [1, 5, 6]))
[(1, 2, 4, 5), (1, 2, 4, 6)]
>>> print list(uprod([1], [1, 2, 4], [1, 5, 6], [1]))
[]
>>> print list(uprod([1, 2], [3, 4]))
[(1, 3), (1, 4), (2, 3), (2, 4)]
这会更有效率,因为甚至从不考虑重复值(既不在输入迭代内,也不在它们之间)。
【讨论】:
为什么这不起作用蒂姆?:In [77]: list(uprod([0, 1],[0, 1],[2, 3, 0, 4, 5, 6, 1],[0, 5],[7, 0, 5],[7, 0, 5],[7, 6, 0, 8, 5],[7, 6, 0, 8, 5],[7, 8, 5],[7, 8, 5])) Out[77]: []
输出看起来对我来说是正确的:将相同的序列传递给itertools.product()
,并且在 113400 个输出 10 元组中的每一个中至少有一个重复项。你认为输出应该是什么?
我只是在 Python 2.7.12 上为list(uprod([0, 1],[0, 1],[2, 3, 0, 4, 5, 6, 1],[0, 5],[7, 0, 5],[7, 0, 5],[7, 6, 0, 8, 5],[7, 6, 0, 8, 5],[7, 8, 5],[7, 8, 5]))
获得了一个空列表@你没有明白吗?
是的,一个空列表。没有没有重复的产品元组,所以所有解决方案的列表都是空的。你明白为什么list(uprod([1], [1]))
是一个空列表吗?同样的事情。
我在想一个与问题略有不同的问题。道歉【参考方案2】:
lis1 = [1,2]
lis2 = [2,4]
lis3 = [5,6]
from itertools import product
print [i for i in product(lis1,lis2,lis3) if len(set(i)) == 3]
输出
[(1, 2, 5), (1, 2, 6), (1, 4, 5), (1, 4, 6), (2, 4, 5), (2, 4, 6)]
【讨论】:
这是一个解决方案,但正如我在问题中所说,这种方法效率不高。假设您在 lis 中有 30 个列表,前两个列表是 [1,0],[1,2]。除非用 (1,1,....) 部分完成,否则它找不到任何解决方案。这非常耗时。 @genclik27 能否给我一些示例数据,它不会起作用? 它会工作但效率不高。比如,lis =[[1,2],[1,3],[4,5],[6,7],[8,9],[10,11],[12,13],[14, 15],[16,17],[18,19],[20,21],[22,23],[24,25],[26,27],[28,29],[30,31] ,[32,33],[34,35],[36,37],[38,39],[40,41],[42,43],[44,45],[46,47]] product(*lis) 将首先执行(1,1,...其他元素),即 2 次方 20 次迭代。编辑它应该是 2 的 20 次方,抱歉。【参考方案3】:使用itertools.combinations
将不会有排序顺序中的重复元素:
>>> lis = [1, 2, 4, 5, 6]
>>> list(itertools.combinations(lis, 3))
[(1, 2, 4), (1, 2, 5), (1, 2, 6), (1, 4, 5), (1, 4, 6), (1, 5, 6), (2, 4, 5),
(2, 4, 6), (2, 5, 6), (4, 5, 6)]
【讨论】:
以上是关于itertools.product 消除重复元素的主要内容,如果未能解决你的问题,请参考以下文章
执行 itertools.product 允许不同迭代次数的不同重复
Python itertools.product 重新排序生成