#python-3.x #algorithm #sorting #quicksort
Вопрос:
Привет! У меня есть список списков, подобных этому:
list_ = [["a", 1],
["b", 3],
["c", 2],
["d", 2]]
Я хочу сортировать каждый второй элемент, и я могу сделать это с помощью быстрой сортировки.
def partition(a, low, high):
i = low - 1
pivot = a[high][1]
for j in range(low, high):
if a[j][1] >= pivot:
i = 1
a[i], a[j] = a[j], a[i]
def quicksort_inplace(a, low=0, high=None):
if high is None:
high = len(a) - 1
if low < high:
p_idx = partition(a, low, high)
quicksort_inplace(a, low, p_idx - 1)
quicksort_inplace(a, p_idx 1, high)
return a
Проблема. Я понимаю, как сортировать по одному элементу за раз, но я не понимаю, как сортировать свой список так, чтобы при наличии одинаковых элементов сортировка происходила в алфавитном порядке (по первому элементу).
в:
[
["a", 1],
["b", 3],
["c", 2],
["d", 2]
]
из:
[
["b", 3],
["d", 2]
["c", 2],
["a", 1],
]
Комментарии:
1. Когда
a[j][1] == pivot
вы не хотите помещать все элементы в одну и ту же часть раздела. Вместо этого разделите их на первый элемент списка.2. В вашем примере также показан обратный порядок сортировки по алфавиту для первого элемента. Это ваш желаемый результат или неверный вывод, который выдает ваш текущий алгоритм?
3. P.S. Я надеюсь, что вы делаете это только в качестве учебного упражнения, потому что вы никогда не превзойдете встроенную сортировку Python.
Ответ №1:
Вы можете просто адаптировать свое сводное значение и функцию сравнения для выполнения любой логики, которую вы хотите, но, как это чаще всего бывает, вы хотите выполнить «лексиографический» порядок. К счастью, python уже реализует эту логику для вас со списками и кортежами, сравнивая первые элементы и, если они равны, переходите к следующему, прежде чем определить, какой из них больше.
Просто используя
pivot = a[high]
...
if a[j] < pivot:
сначала сравнил бы строки, затем число. Однако вам нужен другой порядок, и, кроме того, вы хотите, чтобы числа были перевернуты.
Проще всего просто создать такой key
, по которому можно будет сортировать.
pivot = (-a[high][1], a[high][0]) # reversed number first, then ordinary letter.
...
if (-a[j][1], a[j][0]) < pivot:
Конечно, мы можем использовать их и key
в обычных процедурах сортировки
sorted(list_, key=lambda x: (-x[1], x[0]))
list_.sort(key=lambda x: (-x[1], x[0]))