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 重新排序生成

将大小为 n 的二进制数生成为元组:itertools.product(*[(0, 1)] * n)

消除一个数组中重复的元素

如何消除一个数组里面的重复元素?(面试题目)

如何消除一个数组里面重复的元素?