简体   繁体   English

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

[英]Compute cartesian product of two lists without elements at same index

I have two lists with the same length, say 3. 我有两个长度相同的列表,比如3。

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

I want to get Cartesian product of the two, but the element at the same position shouldn't be count ie : 我想获得两者的笛卡尔积, 同一位置的元素不应该计算,即:

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

How shall I do that? 我该怎么做?

You can nearly directly jot down your 'refined' carthesian product: 您几乎可以直接记下您的“精致”贝塞斯产品:

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

So here's my way to do it use zip() and itertools.product() : 所以我的方法是使用zip()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]

From the document of itertools.product() : itertools.product()的文档:

itertools.product(*iterables, repeat=1)
Cartesian product of input iterables. 输入迭代的笛卡儿乘积。

Equivalent to nested for-loops in a generator expression. 等效于生成器表达式中的嵌套for循环。 For example, product(A, B) returns the same as ((x,y) for x in A for y in B) . 例如, product(A, B)product(A, B) ((x,y) for x in A for y in B)相同((x,y) for x in A for y in B)返回相同的值((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. 此模式创建了一个词典排序,以便在输入的可迭代内容进行排序时,产品元组按排序顺序发出。

And zip() does Make an iterator that aggregates elements from each of the iterables. zip()确实创建了一个迭代器,它聚合了每个迭代的元素。 As the document says. 正如文件所说。


So my code create a set and it has the elements which you don't want, then itertools.product(A, B) produces the full list, if i not in spe removes the elements which you don't want in that list. 所以我的代码创建了一个集合,它有你不想要的元素,然后itertools.product(A, B)生成完整列表, if i not in spe删除你不想要的元素。

Just get the product in the normal way, then filter it out: 只需以正常方式获取产品,然后将其过滤掉:

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

Result: 结果:

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

prod is a generator there, so remember to instead create a comprehension with prod = [...] if you plan on using it more than once. prod是那里的一个生成器,所以如果你计划不止一次使用它,请记住用prod = [...]创建一个理解。

Note that this doesn't work if A and B contain repeated elements. 请注意,如果AB包含重复元素,则不起作用。 To solve this, enumerate it and discard the items with unwanted indices: 要解决此问题,请enumerate它并丢弃带有不需要的索引的项目:

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

Result: 结果:

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

Without any indexing on the lists nor any calculation based on the length of the lists, using plain enumerate 没有列表上的任何索引,也没有基于列表长度的任何计算,使用普通枚举

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

You can iterate list A and iterate list B for each value of list A . 您可以迭代list A并为list A每个值迭代list B If index of both list differs, you can print out the combination of elements from both lists. 如果两个列表的索引不同,则可以打印出两个列表中的元素组合。

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 )

You can try the following approaches. 您可以尝试以下方法。 Since the cartesian product is a set, I will provide my answer as a set of tuples: 由于笛卡尔积是一组,我将把我的答案作为一组元组提供:

Using a set comprehension 使用集合理解

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

I use enumerate(l) in order to have a tuple (index, element) at each iteration in which index is the index of each element of l . 我使用enumerate(l)以便在每次迭代时都有一个元组(index, element) ,其中indexl的每个element的索引。

Using itertools 使用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)}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM