proyectos ejemplos python sorting

python - ejemplos - Ordenar lista basada en valores de otra lista?



django (14)

Tengo una lista de cadenas como esta:

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"] Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1]

¿Cuál es la forma más corta de clasificar X utilizando valores de Y para obtener el siguiente resultado?

["a", "d", "h", "b", "c", "e", "i", "f", "g"]

El orden de los elementos que tienen la misma "clave" no importa. Puedo recurrir al uso de for constructos, pero tengo curiosidad si hay un camino más corto. ¿Alguna sugerencia?


Además, si no te importa usar matrices numpy (o de hecho ya estás tratando con matrices numpy ...), aquí hay otra buena solución:

people = [''Jim'', ''Pam'', ''Micheal'', ''Dwight''] ages = [27, 25, 4, 9] import numpy people = numpy.array(people) ages = numpy.array(ages) inds = ages.argsort() sortedPeople = people[inds]

Lo encontré aquí: http://scienceoss.com/sort-one-list-by-another-list/


Aquí está la respuesta de Whatangs si desea obtener ambas listas ordenadas (python3).

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"] Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1] Zx, Zy = zip(*[(x, y) for x, y in sorted(zip(Y, X))]) print(list(Zx)) # [0, 0, 0, 1, 1, 1, 1, 2, 2] print(list(Zy)) # [''a'', ''d'', ''h'', ''b'', ''c'', ''e'', ''i'', ''f'', ''g'']

Solo recuerda que Zx y Zy son tuplas. También estoy vagando si hay una mejor manera de hacerlo.

Advertencia: si lo ejecutas con listas vacías se bloquea.


Comprima las dos listas juntas, clasifíquelas, luego tome las partes que desee:

>>> yx = zip(Y, X) >>> yx [(0, ''a''), (1, ''b''), (1, ''c''), (0, ''d''), (1, ''e''), (2, ''f''), (2, ''g''), (0, ''h''), (1, ''i'')] >>> yx.sort() >>> yx [(0, ''a''), (0, ''d''), (0, ''h''), (1, ''b''), (1, ''c''), (1, ''e''), (1, ''i''), (2, ''f''), (2, ''g'')] >>> x_sorted = [x for y, x in yx] >>> x_sorted [''a'', ''d'', ''h'', ''b'', ''c'', ''e'', ''i'', ''f'', ''g'']

Combina estos para obtener:

[x for y, x in sorted(zip(Y, X))]


En realidad, vine aquí para ordenar una lista por una lista donde coincidían los valores.

list_a = [''foo'', ''bar'', ''baz''] list_b = [''baz'', ''bar'', ''foo''] sorted(list_b, key=lambda x: list_a.index(x)) # [''foo'', ''bar'', ''baz'']


He creado una función más general, que ordena más de dos listas basadas en otra, inspirada en la respuesta de @ Whatang.

def parallel_sort(*lists): """ Sorts the given lists, based on the first one. :param lists: lists to be sorted :return: a tuple containing the sorted lists """ # Create the initially empty lists to later store the sorted items sorted_lists = tuple([] for _ in range(len(lists))) # Unpack the lists, sort them, zip them and iterate over them for t in sorted(zip(*lists)): # list items are now sorted based on the first list for i, item in enumerate(t): # for each item... sorted_lists[i].append(item) # ...store it in the appropriate list return sorted_lists


La solución más obvia para mí es usar la palabra key clave arg.

>>> X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"] >>> Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1] >>> keydict = dict(zip(X, Y)) >>> X.sort(key=keydict.get) >>> X [''a'', ''d'', ''h'', ''b'', ''c'', ''e'', ''i'', ''f'', ''g'']

Tenga en cuenta que puede acortar esto a una sola línea si le interesa:

>>> X.sort(key=dict(zip(X, Y)).get)


Me gusta tener una lista de índices ordenados. De esa manera, puedo ordenar cualquier lista en el mismo orden que la lista de fuentes. Una vez que tenga una lista de índices ordenados, una simple lista de comprensión hará el truco:

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"] Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1] sorted_y_idx_list = sorted(range(len(Y)),key=lambda x:Y[x]) Xs = [X[i] for i in sorted_y_idx_list ] print( "Xs:", Xs ) # prints: Xs: ["a", "d", "h", "b", "c", "e", "i", "f", "g"]

Tenga en cuenta que la lista de índice ordenada también se puede obtener utilizando numpy argsort ().


Otra alternativa, combinando varias de las respuestas.

zip(*sorted(zip(Y,X)))[1]

Para trabajar en python3:

list(zip(*sorted(zip(B,A))))[1]


Puedes crear una pandas Series , usando la lista principal como data y la otra lista como index , y luego ordenarlas por el índice:

import pandas as pd pd.Series(data=X,index=Y).sort_index().tolist()

salida:

[''a'', ''d'', ''h'', ''b'', ''c'', ''e'', ''i'', ''f'', ''g'']


Un rápido de una sola línea.

list_a = [5,4,3,2,1] list_b = [1,1.5,1.75,2,3,3.5,3.75,4,5]

Digamos que quieres una lista de coincidencias b.

orderedList = sorted(list_a, key=lambda x: list_b.index(x))

Esto es útil cuando se necesita ordenar una lista más pequeña a valores más grandes. Suponiendo que la lista más grande contenga todos los valores en la lista más pequeña, se puede hacer.


zip, ordenar por la segunda columna, devolver la primera columna.

zip(*sorted(zip(X,Y), key=operator.itemgetter(1)))[0]


more_itertools tiene una herramienta para ordenar iterables en paralelo:

from more_itertools import sort_together sort_together([Y, X])[1] # (''a'', ''d'', ''h'', ''b'', ''c'', ''e'', ''i'', ''f'', ''g'')


Código más corto

[x for _,x in sorted(zip(Y,X))]

Ejemplo:

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"] Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1] Z = [x for _,x in sorted(zip(Y,X))] print(Z) # ["a", "d", "h", "b", "c", "e", "i", "f", "g"]

Generalmente hablando

[x for _, x in sorted(zip(Y,X), key=lambda pair: pair[0])]

Explicado:

  1. zip las dos list s.
  2. cree una nueva list ordenada basada en el zip usando sorted() .
  3. utilizando una lista de comprensión, extraiga los primeros elementos de cada par de la list ordenada y comprimida.

Para obtener más información sobre cómo configurar / usar el parámetro key , así como la función sorted en general, eche un vistazo a this .


list1 = [''a'',''b'',''c'',''d'',''e'',''f'',''g'',''h'',''i''] list2 = [0,1,1,0,1,2,2,0,1] output=[] cur_loclist = []

Para obtener valores únicos presentes en la list2

list_set = set(list2)

Para encontrar la ubicación del índice en la list2

list_str = ''''.join(str(s) for s in list2)

La ubicación del índice en la list2 se rastrea mediante cur_loclist

[0, 3, 7, 1, 2, 4, 8, 5, 6]

for i in list_set: cur_loc = list_str.find(str(i)) while cur_loc >= 0: cur_loclist.append(cur_loc) cur_loc = list_str.find(str(i),cur_loc+1) print(cur_loclist) for i in range(0,len(cur_loclist)): output.append(list1[cur_loclist[i]]) print(output)