我有两个列表,一个是规范的好列表,另一个是当前的坏列表。我想尝试坏列表与好列表的所有偏差组合。例如:
good = (0,1,2,3)
bad = (0,10,20,3)
申请运营商后op(good, bad)
,我应该回来
ret = ((0,1,2,3), (0,10,2,3), (0,10,20,3), (0,1,20,3))
子列表的任何顺序。
我正在使用的列表stty -g
是 36 个元素的输出,这些列表相差 16 个元素。
我有两个列表,一个是规范的好列表,另一个是当前的坏列表。我想尝试坏列表与好列表的所有偏差组合。例如:
good = (0,1,2,3)
bad = (0,10,20,3)
申请运营商后op(good, bad)
,我应该回来
ret = ((0,1,2,3), (0,10,2,3), (0,10,20,3), (0,1,20,3))
子列表的任何顺序。
我正在使用的列表stty -g
是 36 个元素的输出,这些列表相差 16 个元素。
压缩好的和坏的列表,将每个结果元组映射到一个集合并将其提供给itertools.product()
:
from itertools import product
for combo in product(*map(set, zip(good, bad))):
print(combo)
演示:
>>> good = (0,1,2,3)
>>> bad = (0,10,20,3)
>>> from itertools import product
>>> for combo in product(*map(set, zip(good, bad))):
... print(combo)
...
(0, 1, 2, 3)
(0, 1, 20, 3)
(0, 10, 2, 3)
(0, 10, 20, 3)
这将采用任何大小的输入;不仅是good
and bad
,还可以添加ugly
:
>>> ugly = (1,2,4,3)
>>> for combo in product(*map(set, zip(good, bad, ugly))):
... print(combo)
...
(0, 1, 4, 3)
(0, 1, 2, 3)
(0, 1, 20, 3)
(0, 10, 4, 3)
(0, 10, 2, 3)
(0, 10, 20, 3)
(0, 2, 4, 3)
(0, 2, 2, 3)
(0, 2, 20, 3)
(1, 1, 4, 3)
(1, 1, 2, 3)
(1, 1, 20, 3)
(1, 10, 4, 3)
(1, 10, 2, 3)
(1, 10, 20, 3)
(1, 2, 4, 3)
(1, 2, 2, 3)
(1, 2, 20, 3)
推广到一个函数:
def op(*sequences):
return product(*map(set, zip(*sequences)))
for combo in op(good, bad):
print(combo)
for combo in op(good, bad, ugly):
print(combo)
因为 aset
用于从每个组合的输入集合中生成唯一值,所以输出顺序与输入的顺序不同。如果 order 很重要,您可以替换set
为dupe-removing order-preserving 函数:
def unique_with_order(seq):
seen = set()
seen_add = seen.add
return [x for x in seq if x not in seen and not seen_add(x)]
def ordered_op(*sequences):
return product(*map(unique_with_order, zip(*sequences)))
它产生根据输入顺序排序的输出:
>>> for combo in ordered_op(good, bad):
... print(combo)
...
(0, 1, 2, 3)
(0, 1, 20, 3)
(0, 10, 2, 3)
(0, 10, 20, 3)
>>> for combo in ordered_op(bad, good):
... print(combo)
...
(0, 10, 20, 3)
(0, 10, 2, 3)
(0, 1, 20, 3)
(0, 1, 2, 3)
你想要的是每个索引的好或坏值的笛卡尔积,除了当好和坏的值相同时,你只想要其中一个,而不是它的两个副本。
所以,让我们压缩这两个列表,并将每个好==坏的组件减少到一个值:
>>> gb = (([g,b] if g!=b else [g] for (g, b) in zip(good, bad))
然后是笛卡尔积:
>>> ret = itertools.product(*gb)
既然你想要它作为一个元组:
>>> ret = tuple(ret)
>>> print ret
((0, 1, 2, 3), (0, 1, 20, 3), (0, 10, 2, 3), (0, 10, 20, 3))