Python itertools.product消除重复的反向元组

Python itertools.product消除重复的反向元组,python,python-2.7,itertools,Python,Python 2.7,Itertools,昨天我问了一个问题,多亏了蒂姆·彼得斯,问题解决了。问题就在这里 新问题是这个问题的进一步版本。这次我将在元组内部生成元组。这是一个例子 lis = [[(1,2), (3,4)], [(5,2), (1,2)], [(2,1), (1,2)]] 当我在itertools.product函数中使用它时,我得到的是 ((1, 2), (5, 2), (2, 1)) ((1, 2), (5, 2), (1, 2)) ((1, 2), (1, 2), (2, 1)) ((1, 2), (1, 2)

昨天我问了一个问题,多亏了蒂姆·彼得斯,问题解决了。问题就在这里

新问题是这个问题的进一步版本。这次我将在元组内部生成元组。这是一个例子

lis = [[(1,2), (3,4)], [(5,2), (1,2)], [(2,1), (1,2)]]
当我在itertools.product函数中使用它时,我得到的是

((1, 2), (5, 2), (2, 1))
((1, 2), (5, 2), (1, 2))
((1, 2), (1, 2), (2, 1))
((1, 2), (1, 2), (1, 2))
((3, 4), (5, 2), (2, 1))
((3, 4), (5, 2), (1, 2))
((3, 4), (1, 2), (2, 1))
((3, 4), (1, 2), (1, 2))
我想改变它,如果一个序列里面有(a,b),那么它就不能有(b,a)。在本例中,如果您查看这个序列
((3,4),(1,2),(2,1))
它的内部有(1,2)和(2,1)。因此,这个序列
((3,4)、(1,2)、(2,1))
不应该在结果中考虑

正如我所说,我以前问过类似的问题,在这种情况下,它并没有考虑重复元素。我试着让它适应我的问题。下面是修改后的代码。在旧版本中更改的部分将记录在注释中

def reverse_seq(seq):
    s = []
    for i in range(len(seq)):
        s.append(seq[-i-1])         
    return tuple(s)


def uprod(*seqs):  
    def inner(i):
        if i == n:
            yield tuple(result)
            return
        for elt in sets[i] - reverse:
            #seen.add(elt)
            rvrs = reverse_seq(elt)
            reverse.add(rvrs)
            result[i] = elt
            for t in inner(i+1):
                yield t
            #seen.remove(elt)
            reverse.remove(rvrs)

    sets = [set(seq) for seq in seqs]
    n = len(sets)
    #seen = set()
    reverse = set()
    result = [None] * n
    for t in inner(0):
        yield t
在我看来,这个代码应该可以工作,但是我的输入
lis=[[(1,2),(3,4)],[(5,2),(1,2)],[(2,1),(1,2)]有错误。
。我不明白我错在哪里

for i in uprod(*lis):
    print i
产出是,

((1, 2), (1, 2), (1, 2))
Traceback (most recent call last):
  File "D:\Users\SUUSER\workspace tree\sequence_covering _array\denemeler_buraya.py", line 39, in <module>
    for i in uprod(*lis):
  File "D:\Users\SUUSER\workspace tree\sequence_covering _array\denemeler_buraya.py", line 32, in uprod
    for t in inner(0):
  File "D:\Users\SUUSER\workspace tree\sequence_covering _array\denemeler_buraya.py", line 22, in inner
    for t in inner(i+1):
  File "D:\Users\SUUSER\workspace tree\sequence_covering _array\denemeler_buraya.py", line 25, in inner
    reverse.remove(rvrs)
KeyError: (2, 1)
((1,2)、(1,2)、(1,2))
回溯(最近一次呼叫最后一次):
文件“D:\Users\SUUSER\workspace tree\sequence\u covering\u array\denemeler\u buraya.py”,第39行,在
对于我在uprod(*lis):
文件“D:\Users\SUUSER\workspace tree\sequence\u covering\u array\denemeler\u buraya.py”,第32行,在UPOD中
对于内部(0)中的t:
文件“D:\Users\SUUSER\workspace tree\sequence\u covering\u array\denemeler\u buraya.py”,第22行,在内部
对于内部的t(i+1):
文件“D:\Users\SUUSER\workspace tree\sequence\u covering\u array\denemeler\u buraya.py”,第25行,在内部
倒车。拆卸(rvrs)
键错误:(2,1)

谢谢,

我做的有点不同,在不需要顺序的地方使用集合来消除顺序。实际上使用了冻结集,所以我们可以很容易地嵌套它们

首先,我们将
lis
转换为(冻结的)集合列表,因为元组的数量顺序应该被忽略

>>> lis = [[(1,2), (3,4)], [(5,2), (1,2)], [(2,1), (1,2)]]
>>> lis_ = [[frozenset(x) for x in y] for y in lis]
接下来,我们创建产品,然后将结果放入一个集合中,这样就可以消除重复项:

>>> result = set(x for x in itertools.product(*lis_))
>>> result
{(frozenset({3, 4}), frozenset({1, 2}), frozenset({1, 2})), (frozenset({1, 2}), frozenset({1, 2}), frozenset({1, 2})), (frozenset({3, 4}), frozenset({2, 5}), frozenset({1, 2})), (frozenset({1, 2}), frozenset({2, 5}), frozenset({1, 2}))}
我们已经完成了。如果您现在打印这些内容,并使其更美观(去掉输出中的
frozenset()
部分,您将得到以下结果:

>>> for r in result:
        print([tuple(x) for x in r])

[(3, 4), (1, 2), (1, 2)]
[(1, 2), (1, 2), (1, 2)]
[(3, 4), (2, 5), (1, 2)]
[(1, 2), (2, 5), (1, 2)]

不同的解决方案,只过滤来自
itertools.product
的结果:

>>> lis = [[(1,2), (3,4)], [(5,2), (1,2)], [(2,1), (1,2)]]
>>> seenProducts = set()
>>> for p in itertools.product(*lis):
        product = tuple(frozenset(x) for x in p)
        if product not in seenProducts:
            seenProducts.add(product)
            print(p) # print original product

((1, 2), (5, 2), (2, 1))
((1, 2), (1, 2), (2, 1))
((3, 4), (5, 2), (2, 1))
((3, 4), (1, 2), (2, 1))

问题是您无条件地执行
反向。删除(rvrs)
,即使
rvrs
在您(冗余地)添加它之前已经处于
反向中。因此插入:

            remove_later = rvrs not in reverse
之前:

            reverse.add(rvrs)
并将删除代码更改为:

            if remove_later:
                reverse.remove(rvrs)
那么输出是:

((1, 2), (1, 2), (1, 2))
((1, 2), (5, 2), (1, 2))
((3, 4), (1, 2), (1, 2))
((3, 4), (5, 2), (1, 2))
((3, 4), (5, 2), (2, 1))
您可以毫不迟疑地扔掉
reverse_seq()
函数,改为编写以下代码:

            rvrs = elt[::-1]

你的意思是一个实际的错误吗?如果是,你能发布错误消息吗?我在帖子中添加了错误消息。谢谢你的回答,但在我的情况下,顺序很重要,这就是我使用元组的原因。如果顺序很重要,那么两个具有相同项但顺序不同的元组被认为是相等的是没有意义的。不,它们不被认为是相等的.我只是不希望它们处于相同的序列中。稍后我将在另一个程序中使用此数据作为输入。如果数据具有(a,b)和(b,a)同时,它返回false。因此,我需要消除这些结果。@genclik27为了公平起见-这是一种应该作为问题的一部分指定的信息,以避免得到实际回答问题的答案,但不完全是因为您没有提到的一些约束或限制:)正如我在问题中所说的,我想比上一个问题更进一步。我在上一个问题中详细解释了一切,这就是为什么我在这里没有提到它。但是,因为排序是一个重要的约束,所以您是对的。我应该是:)对不起。