Что, я думаю, вы спрашиваете
Учитывая два списка одинаковой длины, как я могу отсортировать один, используя значения другого? Например:
to_show = ['a', 'b', 'c', 'd']
to_sort = [100, 200, -50, 700]
assert MAGIC() == ['c', 'a', 'b', 'd']
Как go об этом
Действительно, вы можете получить отсортированную версию одного списка, используя другой очень просто. Давайте использовать sorted
, так как он ничего не меняет на месте, что дружелюбно. Существует много возможных подходов, один из которых может выглядеть следующим образом:
>>> [b for a, b in sorted(zip(to_sort, to_show))]
«умная» версия этого может выглядеть следующим образом:
>>> zip(*sorted(zip(to_sort, to_show)))[1]
('c', 'a', 'b', 'd')
Как это работает
Это делает пару вещей, сначала группирует два списка, используя zip
>>> zip(to_sort, to_show)
[(100, 'a'), (200, 'b'), (-50, 'c'), (700, 'd')]
, затем сортирует эти значения. Python сортирует кортежи на основе первого, затем второго, затем третьего и т. Д. c. Это означает, что мы сначала сортируем по to_sort
и разрываем связи на основе to_show
(без связи с нашими данными).
>>> sorted(zip(to_sort, to_show))
[(-50, 'c'), (100, 'a'), (200, 'b'), (700, 'd')]
В нашей умной версии мы вызываем zip(* ...)
, чтобы "распаковать", что вернуть данные в два списка:
>>> zip(*sorted(zip(to_sort, to_show)))
[(-50, 100, 200, 700), ('c', 'a', 'b', 'd')]
и захватить второй список, to_show
(теперь отсортировано), используя индекс списка:
>>> zip(*sorted(zip(to_sort, to_show)))[1]
('c', 'a', 'b', 'd')
Альтернативный подход с использованием key=
>>> [v for i, v in sorted(enumerate(to_show), key=lambda i_v: to_sort[i_v[0]])]
['c', 'a', 'b', 'd']
Вы можете предпочесть использовать аргумент ключевого слова key
для sort
или sorted
. Цель состоит в том, чтобы сказать «когда вы сортируете элемент 1 из to_show
, просто посмотрите вместо него to_sort
». Для этого мы включим индекс, а затем удалим его.
Мы используем enumerate
, чтобы дать нам индекс со значением
>>> sorted(enumerate(to_show), key=lambda i_v: to_sort[i_v[0]])
[(2, 'c'), (0, 'a'), (1, 'b'), (3, 'd')]
и можем затем следовать тому же обработка, как указано выше (zip
или понимание) для извлечения значения (на этот раз индекс 0
вместо 1
).
Обратите внимание, что нет функции нижеуказанной формы (т.е. игнорирование индексов )
>>> sorted(to_show, key=magic(to_sort))
, который может существовать, при поиске значений от to_show
до to_sort
возникнут проблемы с дублирующимися значениями в to_show
.