Work on each pair of items in a list

Using Python, I would like to compare every possible pair in the list.

Let's pretend that

my_list = [1,2,3,4] 

I would like to do an operation (let it be called foo) for each combination of 2 items from the list.

The end result should be the same as

 foo(1,1) foo(1,2) ... foo(4,3) foo(4,4) 

My first thought was to iterate through the list twice manually, but that doesn't seem very pythonic.

+67
python
Jun 03 '09 at 0:21
source share
4 answers

Check product() in the itertools module. He does exactly what you describe.

 import itertools my_list = [1,2,3,4] for pair in itertools.product(my_list, repeat=2): foo(*pair) 

This is equivalent to:

 my_list = [1,2,3,4] for x in my_list: for y in my_list: foo(x, y) 

Edit: There are two very similar functions: permutations() and combinations() . To illustrate how they differ:

product() generates all possible pairings of elements, including all duplicates:

 1,1 1,2 1,3 1,4 2,1 2,2 2,3 2,4 3,1 3,2 3,3 3,4 4,1 4,2 4,3 4,4 

permutations() generates all the unique orders of each unique pair of elements, excluding duplicates x,x :

  . 1,2 1,3 1,4 2,1 . 2,3 2,4 3,1 3,2 . 3,4 4,1 4,2 4,3 . 

Finally, combinations() only generates each unique pair of elements in lexicographical order:

  . 1,2 1,3 1,4 . . 2,3 2,4 . . . 3,4 . . . . 

All three of these functions were introduced in Python 2.6.

+177
Jun 03 '09 at 0:24
source share

I had a similar problem and found a solution here . It works without having to import any module.

Suppose the list:

 people = ["Lisa","Pam","Phil","John"] 

A simplified single-line solution will look like this.

All possible pairs , including duplicates:

 result = [foo(p1, p2) for p1 in people for p2 in people] 

All possible pairs, excluding duplicates :

 result = [foo(p1, p2) for p1 in people for p2 in people if p1 != p2] 

Unique pairs where order doesn't matter:

 result = [foo(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))] 



If you do not want to work, but just to get pairs, removing the foo function and using only a tuple will be enough.

All possible pairs , including duplicates:

 list_of_pairs = [(p1, p2) for p1 in people for p2 in people] 

Result:

 ('Lisa', 'Lisa') ('Lisa', 'Pam') ('Lisa', 'Phil') ('Lisa', 'John') ('Pam', 'Lisa') ('Pam', 'Pam') ('Pam', 'Phil') ('Pam', 'John') ('Phil', 'Lisa') ('Phil', 'Pam') ('Phil', 'Phil') ('Phil', 'John') ('John', 'Lisa') ('John', 'Pam') ('John', 'Phil') ('John', 'John') 

All possible pairs, excluding duplicates :

 list_of_pairs = [(p1, p2) for p1 in people for p2 in people if p1 != p2] 

Result:

 ('Lisa', 'Pam') ('Lisa', 'Phil') ('Lisa', 'John') ('Pam', 'Lisa') ('Pam', 'Phil') ('Pam', 'John') ('Phil', 'Lisa') ('Phil', 'Pam') ('Phil', 'John') ('John', 'Lisa') ('John', 'Pam') ('John', 'Phil') 

Unique pairs where order doesn't matter:

 list_of_pairs = [(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))] 

Result:

 ('Lisa', 'Pam') ('Lisa', 'Phil') ('Lisa', 'John') ('Pam', 'Phil') ('Pam', 'John') ('Phil', 'John') 

Edit: after the redistribution, to simplify this decision, I realized that this is the same approach as Adam Rosenfield. Hopefully a larger explanation will help some understand this better.

+7
Jun 19 '16 at 13:15
source share

If you just call a function, you cannot do much better than:

 for i in my_list: for j in my_list: foo(i, j) 

If you want to compile a list of function call results, you can do:

 [foo(i, j) for i in my_list for j in my_list] 

which will return you a list of the results of applying foo(i, j) to each possible pair (i, j) .

+1
Jun 03 '09 at 0:29
source share
 my_list = [1,2,3,4] pairs=[[x,y] for x in my_list for y in my_list] print (pairs) 
-one
Jun 07 '19 at 8:13
source share



All Articles