计算两个没有相同索引元素的列表的笛卡尔积

Compute cartesian product of two lists without elements at same index

我有两个长度相同的列表,比如说 3。

A=[1,2,3]
B=[4,5,6]

我想得到两者的笛卡尔积,但是不应该计算相同位置的元素,即:

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

我该怎么做?

只要通过正常方式获取产品,然后筛选出来:

import itertools
A=[1,2,3]
B=[4,5,6]
prod = ((x,y) for x,y in itertools.product(A, B) if A.index(x) != B.index(y))

结果:

>>> for p in prod:
...     print(p)
...
(1, 5)
(1, 6)
(2, 4)
(2, 6)
(3, 4)
(3, 5)

prod 是一个生成器,所以如果您打算多次使用它,请记住使用 prod = [...] 创建一个理解。

请注意,如果 AB 包含重复元素,这将不起作用。要解决这个问题,enumerate 它并丢弃带有不需要索引的项目:

prod = (item for idx,item in enumerate((x,y) for x,y in itertools.product(A, B)) if idx%(len(A)))

结果:

>>> for p in prod:
...     print(p)
...
(1, 5)
(1, 6)
(2, 5)
(2, 6)
(3, 5)
(3, 6)

您几乎可以直接记下您的 'refined' 笛卡尔积:

 ((a[i], b[j]) 
      for i in range(len(a))
      for j in range(len(b))
      if i != j)

所以我的方法是使用 zip() and itertools.product():

import itertools
A = [1, 2, 3]
B = [4, 5, 6]

spe = set(zip(A, B))
l = [i for i in itertools.product(A, B) if i not in spe]

来自itertools.product()的文档:

itertools.product(*iterables, repeat=1)
Cartesian product of input iterables.

Equivalent to nested for-loops in a generator expression. For example, product(A, B) returns the same as ((x,y) for x in A for y in B).

The nested loops cycle like an odometer with the rightmost element advancing on every iteration. This pattern creates a lexicographic ordering so that if the input’s iterables are sorted, the product tuples are emitted in sorted order.

并且 zip() 确实 创建一个迭代器来聚合来自每个可迭代对象的元素。 如文档所述。


所以我的代码创建了一个集合,其中包含您不需要的元素,然后 itertools.product(A, B) 生成完整列表,if i not in spe 删除您不需要的元素列表。

没有对列表进行任何索引,也没有任何基于列表长度的计算,使用普通枚举

>>> g=((a,b) for pa,a in enumerate(A) for pb,b in enumerate(B) if pa!=pb)
>>> for t in g: print(t)
... 
(1, 5)
(1, 6)
(2, 4)
(2, 6)
(3, 4)
(3, 5)

您可以为 list A 的每个值迭代 list A 和迭代 list B。如果两个列表的索引不同,您可以打印出两个列表中元素的组合。

for i in range(len(A)):
        for j in range(len(B)):
                if i != j:
                        print '(',A[i],B[j],')'


( 1 5 )
( 1 6 )
( 2 4 )
( 2 6 )
( 3 4 )
( 3 5 )

您可以尝试以下方法。由于笛卡尔积是一个集合,我将以一组元组的形式提供我的答案:

使用集合理解

>>> A=[1,2,3]
>>> B=[4,5,6]
>>> {(a, b) for i, a in enumerate(A) for j, b in enumerate(B) if i != j}
{(1, 5), (1, 6), (2, 4), (2, 6), (3, 4), (3, 5)}

我使用 enumerate(l) 以便在每次迭代时都有一个元组 (index, element),其中 indexl 的每个 element 的索引。

使用 itertools

>>> import itertools
>>> {(a, b) for a, b in itertools.product(A, B) if A.index(a) != B.index(b)}
{(1, 5), (1, 6), (2, 4), (2, 6), (3, 4), (3, 5)}