2012-03-03 32 views
11

tengo las dos listas en Pythonordenar una lista en Python usando el resultado de la clasificación de otra lista

list_1 = [5, 2, 8]; 
list_2 = ['string1', 'string2', 'string3'] 

quisiera ordenar la lista de puño y utilizar el resultado para ordenar la segunda lista.

En otras palabras, el resultado debería ser:

# Sorted in descending order 
list_1_sorted = [8, 5, 2]; 
list_2_sorted = ['string3', 'string1', 'string2']; 

sé cómo clasificar cada una de estas listas de forma individual, pero ¿cómo puedo permutar una lista mediante la permutación de los índices resultan de la clasificación de la otra lista?

+2

Todavía no está claro lo que quiere decir con "usar el resultado de otro". El ejemplo no ilustra por qué no desea simplemente ordenar ambas listas de forma independiente. – prelic

+3

@prelic: Quiere ordenar 'list_1', y usa la misma permutación para ordenar' list_2'. – Amadan

Respuesta

19

Schwartzian transform

list_1_sorted, list_2_sorted = zip(*sorted(zip(list_1, list_2), 
    key=operator.itemgetter(0), reverse=True)) 
+1

Ugh, quería saber cómo usar el desembalaje para hacer de este un forro, pero no lo suficientemente rápido. +1 para eso y "Transformación de Schwartz". – Wilduck

+1

La 'clave' no es necesaria aquí ya que ese es el orden natural de tuplas. A menos que desee deliberadamente hacer que el tipo sea inestable en el caso de que 'list_1' contenga duplicados ... –

16

Zip las listas juntas, clasificar, descomprimir las listas:

together = zip(list_1, list_2) 
sorted_together = sorted(together) 

list_1_sorted = [x[0] for x in sorted_together] 
list_2_sorted = [x[1] for x in sorted_together] 

Lo que sucede aquí es que zip crea una lista de tuplas, con los elementos que desea que la lista se ordena por ser los primeros elementos:

>>> a = [1,3,7,3,2] 
>>> b = ["one","two",'three','four','five'] 
>>> zip(a,b) 
[(1, 'one'), (3, 'two'), (7, 'three'), (3, 'four'), (2, 'five')] 

Luego, cuando se les ordena, ellos elementos permanecerán sincronizados:

>>> sorted(zip(a,b)) 
[(1, 'one'), (2, 'five'), (3, 'four'), (3, 'two'), (7, 'three')] 

Entonces todo lo que queda es descomprimir estas listas.

+0

+1 para una explicación detallada. –

3

Puede utilizar zip:

>>> list_1 = ['string1', 'string2', 'string3'] 
>>> list_2 = [5, 2, 8] 
>>> s = sorted(zip(list_2, list_1), reverse=True) 
>>> list_1_sorted = [e[1] for e in s] 
>>> list_2_sorted = [e[0] for e in s] 
>>> list_1_sorted 
['string3', 'string1', 'string2'] 
>>> list_2_sorted 
[8, 5, 2] 
>>> 
2

@ respuesta de Ignacio es la mejor, pero por si acaso es necesario ordenar las listas en el lugar sin hacer nuevas listas , puedes probar esto:

import itertools 
list_enumerate = itertools.count() 

list_2.sort(reverse=True, key=lambda k: list_1[next(list_enumerate)]) 
list_1.sort(reverse=True) 
print list_1 
print list_2 

Tenga en cuenta que No creo que haya ninguna garantía de que se llame a la función key para cada elemento de la lista en orden (que es necesario para que esto funcione), por lo que este es un método arriesgado de usar.

+0

No existe tal cosa como un" requisito para operar in situ "en Python. Siempre puede volver a asignar, y si le preocupa la optimización en un nivel de diseño de memoria, de todos modos está usando el idioma equivocado. –

+0

La [dodumentation] (http://wiki.python.org/moin/HowTo/Sorting/#Key_Functions) dice que la función de la tecla es "invocada en cada elemento de la lista antes de hacer comparaciones" y "exactamente una vez para cada registro de entrada" . Tomaría esto como una garantía de que también son llamados en el orden correcto. –

Cuestiones relacionadas