Digamos que tengo dos listas:
list1 = [3, 2, 4, 1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']
Si ejecuto list1.sort()
, lo clasificará, [1,1,2,3,4]
pero ¿hay alguna forma de list2
sincronizar también (por lo que puedo decir que el elemento 4
pertenece 'three'
)? Entonces, el resultado esperado sería:
list1 = [1, 1, 2, 3, 4]
list2 = ['one', 'one2', 'two', 'three', 'four']
Mi problema es que tengo un programa bastante complejo que funciona bien con las listas, pero necesito comenzar a hacer referencia a algunos datos. Sé que esta es una situación perfecta para los diccionarios, pero estoy tratando de evitar los diccionarios en mi procesamiento porque necesito ordenar los valores clave (si debo usar diccionarios, sé cómo usarlos).
Básicamente, la naturaleza de este programa es que los datos vienen en un orden aleatorio (como el anterior), necesito ordenarlos, procesarlos y luego enviar los resultados (el orden no importa, pero los usuarios necesitan saber qué resultado pertenece a qué llave). Pensé en ponerlo primero en un diccionario, luego ordenar la lista uno, pero no tendría forma de diferenciar los elementos con el mismo valor si no se mantiene el orden (puede tener un impacto al comunicar los resultados a los usuarios). Entonces, idealmente, una vez que obtenga las listas, preferiría encontrar una manera de ordenar ambas listas juntas. es posible?
Respuestas:
Un enfoque clásico para este problema es usar el modismo "decorar, ordenar, decorar", que es especialmente simple usando la función incorporada de python
zip
:Estas, por supuesto, ya no son listas, pero eso se puede remediar fácilmente, si es importante:
Vale la pena señalar que lo anterior puede sacrificar la velocidad por la brevedad; la versión in situ, que ocupa 3 líneas, es un poco más rápida en mi máquina para listas pequeñas:
Por otro lado, para listas más grandes, la versión de una línea podría ser más rápida:
Como Quantum7 señala, la sugerencia de JSF es un poco más rápida aún, pero probablemente solo sea un poco más rápida, porque Python usa el mismo idioma de DSU internamente para todo tipo de claves. Simplemente está sucediendo un poco más cerca del metal desnudo. (¡Esto muestra cuán optimizadas están las
zip
rutinas!)Creo que el
zip
enfoque basado en la base es más flexible y un poco más legible, así que lo prefiero.fuente
*
operador hace el desempaque de argumentos ,zip(*x)
tiene la interesante propiedad de que es su propio inverso:l = [(1, 2), (3, 4)]; list(zip(*zip(*l))) == l
retornosTrue
. Es efectivamente un operador de transposición.zip()
por sí solo es el mismo operador, pero supone que ha desempaquetado la secuencia de entrada manualmente.Puede ordenar los índices utilizando valores como claves:
Para obtener listas ordenadas dados índices ordenados:
En su caso, no debería tener
list1
,list2
sino una sola lista de pares:Es fácil de crear; es fácil de ordenar en Python:
Ordenar solo por el primer valor:
fuente
list()
todomap()
, si desea utilizar este código en Python 3.sorted_list1 = list(map(list1.__getitem__, indexes))
uno, podría hacerlosorted_list1 = [list1[i] for i in indexes]
.He usado la respuesta dada por senderle durante mucho tiempo hasta que descubrí
np.argsort
. Así es como funciona.Encuentro esta solución más intuitiva y funciona muy bien. El rendimiento:
Aunque
np.argsort
no es el más rápido, me resulta más fácil de usar.fuente
TypeError: only integer arrays with one element can be converted to an index
(Python 2.7.6, numpy 1.8.2). Para solucionarlo, list1 y list2 deben declararse como matrices numpy.np.argsort
no intentes convertir a unnp.array
interno.Transformación de Schwartz . La clasificación de Python incorporada es estable, por lo que los dos
1
s no causan ningún problema.fuente
Qué pasa:
fuente
Puede usar las funciones
zip()
ysort()
para lograr esto:Espero que esto ayude
fuente
Puede usar el argumento clave en el método sorted () a menos que tenga dos mismos valores en list2.
El código se da a continuación:
Ordena list2 según los valores correspondientes en list1, pero asegúrese de que al usar esto, no haya dos valores en list2 que sean iguales porque la función list.index () proporciona el primer valor
fuente
Una forma es rastrear a dónde va cada índice clasificando la identidad [0,1,2, .. n]
Esto funciona para cualquier cantidad de listas.
Luego mueva cada elemento a su posición. Usar empalmes es lo mejor.
Tenga en cuenta que podríamos haber iterado las listas sin siquiera ordenarlas:
fuente
Si está usando numpy, puede usarlo
np.argsort
para obtener los índices ordenados y aplicar esos índices a la lista. Esto funciona para cualquier número de lista que desee ordenar.fuente
Una solución algorítmica:
Salidas:
->
Velocidad de salida:0.2s
fuente
Otro enfoque para retener el orden de una lista de cadenas al ordenar en otra lista es el siguiente:
salida
fuente
Me gustaría ampliar la respuesta de jfs abierta , que funcionó muy bien para mi problema: ordenar dos listas por una tercera lista decorada :
Podemos crear nuestra lista decorada de cualquier manera, pero en este caso la crearemos a partir de los elementos de una de las dos listas originales, que queremos ordenar:
Ahora podemos aplicar la solución de jfs para ordenar nuestras dos listas por la tercera
Editar: Hola chicos, hice una publicación en bloque sobre esto, échale un vistazo si te apetece :) 🐍🐍🐍
fuente
fuente