2009-06-03 16 views
50

Usando Python, me gustaría comparar cada par posible en una lista.Operación en cada par de elementos en una lista

Supongamos que tengo

my_list = [1,2,3,4] 

me gustaría hacer una operación (llamémoslo foo) en todas las combinaciones de 2 elementos de la lista.

El resultado final debe ser el mismo que

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

Mi primer pensamiento fue para repetir dos veces a través de la lista de forma manual, pero eso no parece muy Pythonic.

Respuesta

141

Consulte product() en el módulo itertools. Hace exactamente lo que describes.

import itertools 

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

Esto es equivalente a:

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

Editar: Hay dos funciones muy similares, así, permutations() y combinations(). Para ilustrar cómo se diferencian:

product() genera cada posible apareamiento de elementos, incluyendo todos los duplicados:

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() genera todos los ordenamientos únicas de cada par de elementos únicos, eliminando los x,x duplicados:

. 1,2 1,3 1,4 
2,1 . 2,3 2,4 
3,1 3,2 . 3,4 
4,1 4,2 4,3 . 
Por último, combinations() solo genera cada par único de elementos, en orden lexicográfico:
. 1,2 1,3 1,4 
. . 2,3 2,4 
. . . 3,4 
. . . . 

Las tres funciones se introdujeron en Python 2.6.

+1

No sabía acerca de itertools, esto es perfecto. Gracias ! – GuiSim

+1

Extraño, cuando ejecuto itertools.product (mi_lista, 2), se queja de que int no se puede llamar. Funciona una vez que lo cambio a: itertools.product (mi_lista, repeat = 2) – ojrac

+0

(usando Python 2.6.2) – ojrac

2

Si acaba de llamar a una función, realmente no se puede hacer mucho mejor que:

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

Si desea recopilar una lista de los resultados de llamar a la función, que puede hacer:

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

que le devolverá una lista del resultado de aplicar foo(i, j) a cada posible par (i, j).

5

Tuve un problema similar y encontré la solución here. Funciona sin tener que importar ningún módulo.

Suponiendo una lista como:

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

Una solución simplificada de una línea se vería así.

todos los posibles pares, incluyendo duplicados:

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

todos los posibles pares, con exclusión de duplicados:

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

pares únicos, donde el orden es irrelevante:

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

En caso de que no desee operar pero solo para obtener los pares, eliminar la función foo y usar solo una tupla sería suficiente.

todos los posibles pares, incluyendo duplicados:

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

Resultados:

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

todos los posibles pares, con exclusión de duplicados:

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

Resultado:

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

pares únicos, donde el orden es irrelevante:

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

Resultado:

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

Editar: Después de la reanudación para simplificar esta solución, me di cuenta que es el mismo enfoque que Adam Rosenfield. Espero que la explicación más grande ayude a algunos a entenderlo mejor.

+1

¡Prefiero esto a importar una biblioteca, mucho más limpio! –

Cuestiones relacionadas