昨天我问了一个问题,感谢Tim Peters,它已经解决了。问题在这里;
itertools.product eliminating repeated elements
新问题是这个的进一步版本。这次我将在元组内部生成元组。这是一个例子;
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)
谢谢,
答案 0 :(得分:1)
我的做法有点不同,使用套装来摆脱不需要订单的顺序。实际上使用frozensets,所以我们可以很容易地嵌套它们。
首先,我们将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))
答案 1 :(得分:1)
问题是,在您(冗余地)添加reverse.remove(rvrs)
rvrs
之前,reverse
已经<{1}}无条件执行 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]
函数并改为编写:
{{1}}