Может ли сортировка Python с помощью ключа передать мне порядковую позицию элемента в исходном списке вместо самого элемента

#python #sorting

#python #сортировка

Вопрос:

У меня есть список элементов, которые мне нужно отсортировать, но значение, которое я хочу использовать при сортировке для каждого элемента, отсутствует в самом списке. Информация о сортировке находится в другом списке, который позиционно совпадает с первым.

Т. е. l = список элементов для сортировки, v = список значений для сортировки. При сортировке l[0] следует использовать значение в v[0] .

Поэтому во время сортировки мне нужно, чтобы python сообщал мне порядковую позицию сортируемого элемента, вместо того, чтобы указывать сам элемент.

Настолько эффективно, что я бы сделал это:

 l = sort(key = lambda index_of_item: v[index_of_item])
  

По умолчанию я думаю, что это не сработает, поскольку python вызывает эту лямбду с фактическим элементом из l, а не с позицией элемента. Есть ли способ заставить python указать мне позицию вместо этого?

(Если бы в каждом сортируемом элементе был какой-то идентификатор, я мог бы использовать его сам внутри лямбда-выражения для экстраполяции index_of_item, но, к сожалению, этого нет)

Комментарии:

1. list.index() или enumerate() должно быть жизнеспособным для этого

2. можете ли вы показать несколько тестовых примеров? пример ввода и вывода?

Ответ №1:

Преобразуйте свой список элементов в список кортежей, который включает исходный индекс; это можно сделать с помощью enumerate() . Затем вы можете использовать этот индекс для доступа к другому списку.

 augumented_list = list(enumerate(l))
augmented_list.sort(key = lambda item: v[item[0]])
result = [x[1] for x in augmented_list]
  

Другой вариант — использовать zip() для объединения элементов обоих списков, а затем использовать значение из другого списка в качестве ключа сортировки.

 result = [x[0] for x in sorted(zip(l, v), key = lambda x: x[1])]
  

Комментарии:

1. Пока вы полагаетесь на enumerate , вы также можете использовать sorted для объединения list ification и сортировки в один шаг: augmented_list = sorted(enumerate(l), key=lambda item: v[item[0]])

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

3. ответом был enumerate, но это немного некрасиво — вам нужно «избавиться» от порядковых номеров перечисления после сортировки. Было бы здорово, если бы python каким-то образом необязательно передавал индекс элемента, обеспечивая дополнительный уровень косвенности

4. Тот факт, что у вас есть два отдельных списка для связанных данных, в первую очередь указывает на плохие структуры данных. объедините их в список кортежей или словарей.

5. @MichaelRayLovett: Если вы действительно ненавидите это, «умный» способ сделать это, который я настоятельно не рекомендую , — полагаться на то, что он генерирует ключи для каждого элемента по порядку. Таким образом, вы могли бы обойтись без ручного оформления, выполнив: l.sort(key=lambda _, it=iter(v): next(it)) . Работает с оригиналом l без ручного оформления ( key аргументы неявно украшают, сортируют и отменяют оформление, но вам не нужно делать это самостоятельно). ЧТОБЫ БЫЛО ЯСНО, ЭТО УЖАСНАЯ ИДЕЯ! Ничто официально не требует генерации ключей по порядку, это просто естественный способ сделать это.