Python 计算在同一索引中没有元素的两个列表的笛卡尔积

Python 计算在同一索引中没有元素的两个列表的笛卡尔积,python,set,Python,Set,我有两个相同长度的列表,比如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))

我有两个相同长度的列表,比如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)
>>> for p in prod:
...     print(p)
...
(1, 5)
(1, 6)
(2, 5)
(2, 6)
(3, 5)
(3, 6)
prod
是一个生成器,因此如果您计划多次使用它,请记住使用
prod=[…]
创建一个理解

请注意,如果
A
B
包含重复的元素,则这不起作用。要解决此问题,
枚举
并丢弃带有不需要的索引的项目:

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, 4)
(2, 6)
(3, 4)
(3, 5)
>>> for p in prod:
...     print(p)
...
(1, 5)
(1, 6)
(2, 5)
(2, 6)
(3, 5)
(3, 6)

您几乎可以直接记下您的“精制”卡瑟斯产品:

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

因此,以下是我的方法:


itertools.product()
的文档中:

itertools.product(*iterables,repeat=1)

输入变量的笛卡尔积

等效于生成器表达式中的嵌套for循环。例如,
产品(A,B)
返回的值与
相同(A中x的(x,y)表示B中y的值)

嵌套循环像里程表一样循环,最右边的元素在每次迭代中前进。该模式创建了一个字典顺序,这样,如果输入的iterables被排序,那么产品元组将按排序顺序发出

而且
zip()
确实生成了一个迭代器,用于聚合来自每个iterable的元素。正如文件所说



因此,我的代码创建一个集合,它包含您不需要的元素,然后
itertools.product(a,B)
生成完整的列表,
如果我不在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)

对于
列表A
的每个值,可以迭代
列表A
列表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 )

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

使用集合理解 我使用
enumerate(l)
以便在每次迭代中都有一个元组
(索引,元素)
,其中
index
l
的每个
元素的索引

使用itertools
A=[1,1,1]xb=[2,2,2]
会发生什么?“返回值为x的第一个项目列表中的索引。如果没有此类项目,则为错误。”两个问题:(1)理解测试中的测试会在性能上增加一个系数n,因为它会在两个列表中搜索每个结果项目。不是O(n^2),而是O(n^3)。和(2)如果任一列表包含重复元素,则它将失败。考虑a=[1,1]和b=[2,3]。结果应该是[(1,3),(1,2)],但这会错误地给出[(!,3),(1,2)]。然后它会中断,但问题没有指定重复的元素。不过,我会修复它。:)列表中的值不应对选择过程产生影响。如果其中一个列表中的两个值恰好相同,则结果中的相应值将相同。这是明确的解决方案。事实上,我正要发布基本相同的东西,直到我看到你已经有:)就代码大小而言,这扩展到多个
list
s的效果如何?@TigerhawkT3:N(len(list))。对于多个列表,必须添加一个子句,并且必须将条件更改为
not(i==j或i==k或…
)。如果事先不知道操作数,则需要一个helper函数。但也许你最好还是使用numpy之类的工具。这就是为什么我要坚持使用
itertools.product
,是的。我想每种方法都有它的缺点。初学者更容易理解这个答案。仅仅一个代码块并不能提供一个好的答案。请添加解释(为什么它能解决问题、错误在哪里等)@LouisBarranqueiro更新,因为您提到了
set
。。。
set(产品(A,B))-set(邮政编码(A,B))
怎么样?想想看。。。由于筛选是基于值而不是索引,因此这不适用于特殊产品([1,1],[1,1])
。我刚刚为您的问题添加了一个答案!
>>> 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)}