简体   繁体   中英

Compute cartesian product of two lists without elements at same index

I have two lists with the same length, say 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() :

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(*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.

And zip() does Make an iterator that aggregates elements from each of the iterables. 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.

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.

Note that this doesn't work if A and B contain repeated elements. To solve this, enumerate it and discard the items with unwanted indices:

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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