Сортировка списка на основе значений из другого списка?



у меня есть список строк, как это:



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


каков самый короткий способ сортировки X с использованием значений из Y для получения следующего вывода?



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


порядок элементов, имеющих один и тот же" ключ " не имеет значения. Я могу прибегнуть к использованию for конструкции, но мне любопытно, если есть более короткий путь. Есть предложения?

445   14  

14 ответов:

Самый Короткий Код

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

пример:

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"]

В Целом

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

пояснил:

  1. zip два list s.
  2. создать новый, отсортированный list на основе zip используя sorted().
  3. используя понимание списка экстракт первый элементы каждой пары из отсортированных, zipped list.

для получения дополнительной информации о том, как установить\использовать

Zip два списка вместе, сортировать его, а затем взять части, которые вы хотите:

>>> 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']

объединить их вместе, чтобы получить:

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

кроме того, если вы не возражаете использовать массивы numpy (или на самом деле уже имеете дело с массивами numpy...), вот еще одно хорошее решение:

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]

Я нашел его здесь: http://scienceoss.com/sort-one-list-by-another-list/

наиболее очевидным решением для меня является использование key ключевое слово 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']

обратите внимание, что вы можете сократить это до одного лайнера, если вы хотите:

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

Мне нравится иметь список отсортированных индексов. Таким образом, я могу сортировать любой список в том же порядке, что и исходный список. Если у вас есть список отсортированных индексов, простое понимание списка сделает трюк:

    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"]

обратите внимание, что список отсортированных индексов также можно получить с помощью numpy argsort().

еще один вариант, объединяющий несколько ответов.

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

для того, чтобы работать на python3:

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

zip, сортировка по второму столбцу, возврат первого столбца.

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

more_itertools имеет инструмент для сортировки итераций параллельно:

from more_itertools import sort_together

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

быстрый ОДН-вкладыш.

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

скажем, вы хотите, чтобы список a соответствовал списку b.

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

это полезно при необходимости заказать меньший список значений в большем. Предполагая, что большой список содержит все значения в меньшем списке, это можно сделать.

Я создал более общую функцию, которая сортирует более двух списков на основе другого, вдохновленного ответом @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

Я на самом деле пришел сюда, чтобы отсортировать список по списку, где значения совпадают.

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

вы можете создать pandas Series, используя основной список как data а другой список как index, а потом просто Сортировать по индексу:

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

выход:

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

вот ответ Whatangs, если вы хотите получить оба отсортированных списка (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']

просто помните, что ZX и Zy-это кортежи. Я тоже бродил, если есть лучший способ сделать это.

предупреждение: если вы запустите его с пустыми списками она падает.

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

output=[]
cur_loclist = []

чтобы получить уникальные значения в list2

list_set = set(list2)

чтобы найти loc индекса в list2

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

расположение индекса в list2 отслеживается с помощью 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)

Comments

    Ничего не найдено.