Python 两个列表差异的所有组合

Python 两个列表差异的所有组合,python,combinatorics,Python,Combinatorics,我有两个列表,一个是规范的好的列表,另一个是当前的坏的列表。我想尝试坏列表与好列表的所有偏差组合。例如: good = (0,1,2,3) bad = (0,10,20,3) 在应用操作符op(好的,坏的)之后,我应该回去了 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(好的,坏的)
之后,我应该回去了

ret = ((0,1,2,3), (0,10,2,3), (0,10,20,3), (0,1,20,3))
以子列表的任何顺序


我正在处理的列表是stty-g的输出,它是36个元素,列表之间相差16个元素。

您需要的是每个索引的好值或坏值的笛卡尔乘积,除了当好值和坏值相同时,您只需要其中一个,而不是两个副本

因此,让我们压缩这两个列表,并将good==bad的每个组件缩减为一个值:

>>> 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))

你想要的是每个索引上好的或坏的值的笛卡尔积,除了当好的和坏的值相同时,你只想要其中一个,而不是它的两个副本

因此,让我们压缩这两个列表,并将good==bad的每个组件缩减为一个值:

>>> 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))

压缩好的和坏的列表,将每个结果元组映射到一个集合,并将其馈送到
itertools.product()

演示:

这将需要任何大小的输入;不仅仅是
好的
坏的
,还可以添加
丑陋的

>>> 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)
由于
集合
用于从每个组合输入集合生成唯一值,因此输出顺序与输入顺序不同。如果顺序很重要,您可以将
set
替换为:

它根据输入的顺序生成有序的输出:

>>> 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)

压缩好的和坏的列表,将每个结果元组映射到一个集合,并将其馈送到
itertools.product()

演示:

这将需要任何大小的输入;不仅仅是
好的
坏的
,还可以添加
丑陋的

>>> 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)
由于
集合
用于从每个组合输入集合生成唯一值,因此输出顺序与输入顺序不同。如果顺序很重要,您可以将
set
替换为:

它根据输入的顺序生成有序的输出:

>>> 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)