2011-02-24 11 views
7

supongamos que hubiese algo como esto:conseguir todas las combinaciones posibles en una lista

L1=['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse'...] 

for x in L1: 
    input1= open('file_%s'%(x), 'r') 
    file1= pickle.load(input1) 
    for x in L1: 
     input2= open('file_%s'%(x), 'r') 
     file2= pickle.load(input2) 

y quería obtener todas las combinaciones de archivos sin necesidad de repetir las combinaciones que ya se han hecho (una vez cat_dog se hace no hacer dog_cat de nuevo). ¿Hay alguna manera de que yo pueda hacer esto? Mi lista real está en orden alfabético, si eso hace alguna diferencia.

+4

esto se ha preguntado muchas veces así que probablemente se cerrará. importar itertools; itertools.combinations (['cat', 'dog', 'fish'], 2) – DisplacedAussie

+0

posible duplicado de [código de Python para seleccionar todas las combinaciones posibles de una lista?] (http: // stackoverflow.com/questions/464864/python-code-to-pick-out-all-possible-combinations-from-a-list) – tzot

Respuesta

5

también puede hacerlo como un generador:

L1=['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse'] 
tuples = [(x,y) for x in L1 for y in L1 if x != y] 
for entry in tuples: 
    if (entry[1], entry[0]) in tuples: 
     tuples.remove((entry[1],entry[0])) 
for pair in tuples: 
    input1= open('file_%s'%(pair[0]), 'r') 
    file1= pickle.load(input1) 
    input2= open('file_%s'%(pair[1]), 'r') 
    file2= pickle.load(input2) 

Después del primer bucle, el contenido de tuples es:

('cat', 'dog') 
('cat', 'fish') 
('cat', 'rabbit') 
('cat', 'horse') 
('cat', 'bird') 
('cat', 'frog') 
('cat', 'mouse') 
('dog', 'fish') 
('dog', 'rabbit') 
('dog', 'horse') 
('dog', 'bird') 
('dog', 'frog') 
('dog', 'mouse') 
('fish', 'rabbit') 
('fish', 'horse') 
('fish', 'bird') 
('fish', 'frog') 
('fish', 'mouse') 
('rabbit', 'horse') 
('rabbit', 'bird') 
('rabbit', 'frog') 
('rabbit', 'mouse') 
('horse', 'bird') 
('horse', 'frog') 
('horse', 'mouse') 
('bird', 'frog') 
('bird', 'mouse') 
('frog', 'mouse') 
+0

esto es perfecto, justo lo que necesitaba gracias @Nate! – marsx

+2

Esta no es una gran manera de hacerlo. ¡Mira la solución itertools! Itertools evita tener que generar la lista completa por adelantado: en esta implementación, la lista de tuplas es n^2 elementos. La solución itertools no necesita almacenar la lista. –

2

Hay itertools que pueden realizar combinaciones y permutaciones (querría la primera). Por lo que puedo decir, realmente no se puede especificar el formato de salida, por lo que obtendrías "catdog" como salida, pero la página de documentación te da una idea de cómo funciona la función de combinaciones, para que puedas adaptarla a la construcción Que necesitas.

4

¿Qué tal itertools.combinations?

Ejemplo de uso:

>>> list(itertools.combinations([1, 2, 3, 4, 5, 6], 2)) 
[(1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (2, 5), (2, 6), (3, 4), 
(3, 5), (3, 6), (4, 5), (4, 6), (5, 6)] 

primer argumento es un iterable, segundo es r, longitud de subsecuencias regresó.

continuación, puede concatenar los resultados con facilidad en el mapa o una comprensión:

map(lambda x: x[0] + "_" + x[1], itertools.combinations(["cat", "dog", "fish"], 2))) 

x en el Lambda es una tupla -sized r.

El resultado de lo anterior sería:

['cat_dog', 'cat_fish', 'dog_fish'] 
22

En realidad lo que estás preguntando cómo hacer es producir todas las combinaciones de dos elementos tomados de la lista de nombres (en contraposición a todo la posible combinación de ellos).

Eso significa que puede utilizar los pares incorporados itertools.combinations() función de generador de forma fácil (y eficiente) generan de los nombres que desee sin repeticiones:

L1 = ['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse'] 

for pair in combinations(L1, 2): 
    print(pair) 
    input1 = open('file_%s' % pair[0], 'r') 
    input2 = open('file_%s' % pair[1], 'r') 

pares procesados:

('cat', 'dog') 
('cat', 'fish') 
('cat', 'rabbit') 
('cat', 'horse') 
('cat', 'bird') 
('cat', 'frog') 
('cat', 'mouse') 
('dog', 'fish') 
('dog', 'rabbit') 
('dog', 'horse') 
('dog', 'bird') 
('dog', 'frog') 
('dog', 'mouse') 
('fish', 'rabbit') 
('fish', 'horse') 
('fish', 'bird') 
('fish', 'frog') 
('fish', 'mouse') 
('rabbit', 'horse') 
('rabbit', 'bird') 
('rabbit', 'frog') 
('rabbit', 'mouse') 
('horse', 'bird') 
('horse', 'frog') 
('horse', 'mouse') 
('bird', 'frog') 
('bird', 'mouse') 
('frog', 'mouse') 
3
import itertools 
import cPickle 

def unique_pairs(lst): 
    return itertools.combinations(lst, 2) 

FNAME = "file_{0}".format 
def load_pickle(fname): 
    with open(fname) as inf: 
     return cPickle.load(inf) 

def naive_method(lst): 
    # load each file every time it is requested 
    for x,y in unique_pairs(lst): 
     input1 = load_pickle(FNAME(x)) 
     input2 = load_pickle(FNAME(y)) 
     # do something with input1 and input2 

def better_method(lst): 
    # if you have enough memory for it! 
    dat = [load_pickle(FNAME(i)) for i in lst] 
    for x,y in unique_pairs(range(len(lst))): 
     input1 = dat[x] 
     input2 = dat[y] 
     # do something with input1 and input2 
0

Una alternativa para la creación de combinación, sin importación de módulo. Similar a @ respuesta de Nate, pero un poco menos complejo, creando una copia de los objetos individuales y la reducción sobre la marcha (en vez de generar una lista de pares y reducir a la búsqueda lista):

L1 = ['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse'] 
Laux = L1[:] 

pairs = [] 
for a in L1: 
    Laux.remove(a) 
    for b in Laux: 
     pairs += [(a,b)] 
Cuestiones relacionadas