Разобраться с сортировкой и заполнить эту статью.
Примечание. Самая простая разница между sort()
и sorted()
заключается в следующем: sort()
изменяет список напрямую и не возвращает никакого значения, а sorted()
не изменяет список, но возвращает отсортированный список.
другими словами
sort()
Метод не возвращает никакого значения, он меняет исходный список. Если вы хотите, чтобы функция возвращала отсортированный список, а не изменяла исходный список, используйте sorted()
.
По умолчанию sort()
не требует дополнительных параметров. Однако у него есть два необязательных параметра:
- reverse — Если
True
, отсортированный список перевернут (или отсортирован в порядке убывания) - key — функция, которая служит ключом для сравнения сортировок
https://docs.python.org/3/howto/sorting.html
https://www.programiz.com/python-programming/methods/list/sort
https://tproger.ru/translations/python-sorting/
Пример № 1
# random list random = [(2, 2), (3, 4), (4, 1), (1, 3)] # sort list with key random.sort() # print list print('Sorted list:', random) # Sorted list: [(1, 3), (2, 2), (3, 4), (4, 1)]
Результат вывода:
Sorted list: [(1, 3), (2, 2), (3, 4), (4, 1)]
Пример № 2
# random list random = [(2, 2), (3, 4), (4, 1), (1, 3)] # take second element for sort def takeSecond(elem): return elem[1] # sort list with key random.sort(key=takeSecond) # print list print('Sorted list:', random) # Sorted list: [(4, 1), (2, 2), (1, 3), (3, 4)]
Результат вывода:
Sorted list: [(4, 1), (2, 2), (1, 3), (3, 4)]
В Примере №2 ключу «key» присваиваем ссылку на функцию «takeSecond».
При выполнении строки «random.sort(key=takeSecond)» каждый элемент из списка [(2, 2), (3, 4), (4, 1), (1, 3)] передается в качестве аргумента функции, т.е.
(2, 2)
(3, 4)
(4, 1)
(1, 3)
Функция возвращает 2 элемент «return elem[1]«, т.е. «2, 4, 1, 3» и по этому значению производиться сортировка.
Пример № 3
Сортировка словаря по одному из ключей,
Сортировка списков по ключу.
У списков есть метод sort(), который сортирует элементы. Также есть аргумент reverse, с помощью которого можно отсортировать в обратном порядке при значении True.
Но еще есть аргумент key, отвечающий за критерий сортировки. Он принимает функцию, которая применяется к каждому элементу. Возвращаемый результат и есть критерий, по которому произойдет сортировка.
В примере ниже у нас есть список из словарей, которые содержать описания машин. Мы отсортировали список по годам их выпуска, то есть по ключу ‘year’.
использую lambda (анонимные функция)
cars = [ {'brand1': 'Ford', 'year': 2005}, {'brand': 'Mitsubishi', 'year': 2000}, {'brand': 'BMW', 'year': 2019}, {'brand': 'VW', 'year': 2011} ] print('Было\n', cars, '\n') cars.sort(key = lambda car: car['year']) print('Стало\n', cars)
или использую Функцию
cars = [ {'brand1': 'Ford', 'year': 2005}, {'brand': 'Mitsubishi', 'year': 2000}, {'brand': 'BMW', 'year': 2019}, {'brand': 'VW', 'year': 2011} ] def function_jp(car): return car['year'] print('Было\n', cars, '\n') cars.sort(key = function_jp) print('Стало\n', cars)
Результат вывода:
Было
[{'brand1': 'Ford', 'year': 2005}, {'brand': 'Mitsubishi', 'year': 2000}, {'brand': 'BMW', 'year': 2019}, {'brand': 'VW', 'year': 2011}]
Стало
[{'brand': 'Mitsubishi', 'year': 2000}, {'brand1': 'Ford', 'year': 2005}, {'brand': 'VW', 'year': 2011}, {'brand': 'BMW', 'year': 2019}]
Пример № 4
# sorting using custom key employees = [ {'Name': 'Alan Turing', 'age': 25, 'salary': 10000}, {'Name': 'Sharon Lin', 'age': 30, 'salary': 8000}, {'Name': 'John Hopkins', 'age': 18, 'salary': 1000}, {'Name': 'Mikhail Tal', 'age': 40, 'salary': 15000}, ] def print_jp(dict_jp): # Вывод построчно передаваемого списка for s in dict_jp: print(s) print('\n\n') # настраиваемые функции для получения информации о сотрудниках def get_name(employee): # Будем сортировать по ключую 'Name' return employee['Name'] # return employee.get('Name') # Аналог def get_age(employee): # Будем сортировать по ключую 'age' return employee['age'] # return employee.get('age') # Аналог def get_salary(employee): # Будем сортировать по ключую 'salary' return employee['salary']# return employee.get('') # Аналог # sort by name (Ascending order) employees.sort(key=get_name) print_jp(employees) # sort by Age (Ascending order) employees.sort(key=get_age) print_jp(employees) # sort by salary (Descending order) employees.sort(key=get_salary, reverse=True) print_jp(employees)
Результат вывода:
{'Name': 'Alan Turing', 'age': 25, 'salary': 10000}
{'Name': 'John Hopkins', 'age': 18, 'salary': 1000}
{'Name': 'Mikhail Tal', 'age': 40, 'salary': 15000}
{'Name': 'Sharon Lin', 'age': 30, 'salary': 8000}
{'Name': 'John Hopkins', 'age': 18, 'salary': 1000}
{'Name': 'Alan Turing', 'age': 25, 'salary': 10000}
{'Name': 'Sharon Lin', 'age': 30, 'salary': 8000}
{'Name': 'Mikhail Tal', 'age': 40, 'salary': 15000}
{'Name': 'Mikhail Tal', 'age': 40, 'salary': 15000}
{'Name': 'Alan Turing', 'age': 25, 'salary': 10000}
{'Name': 'Sharon Lin', 'age': 30, 'salary': 8000}
{'Name': 'John Hopkins', 'age': 18, 'salary': 1000}
Пример № 5
Функции модуля operator
Python предоставляет удобные функции, упрощающие и ускоряющие реализацию сортировки.
Модуль operator
имеет itemgetter()
, attrgetter()
и methodcaller()
функцию.
Используя эти функции, приведенные выше примеры становятся проще и быстрее:
student_tuples = [ ('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10), ] from operator import itemgetter, attrgetter print( sorted(student_tuples, key=itemgetter(1, 2)) )
Результат вывода: сперва сортируется по 2-у аргументу, а уже потом по 3-му аргументу.
[(‘john’, ‘A‘, 15), (‘dave’, ‘B‘, 10), (‘jane’, ‘B‘, 12)]
from operator import itemgetter, attrgetter class Student: def __init__(self, name, grade, age): self.name = name self.grade = grade self.age = age def __repr__(self): return repr((self.name, self.grade, self.age)) student_objects = [ Student('john', 'A', 15), Student('jane', 'B', 12), Student('dave', 'B', 10) ] print( sorted(student_objects, key=attrgetter('grade', 'age')) )
Результат вывода:
[(‘john’, ‘A‘, 15), (‘dave’, ‘B‘, 10), (‘jane’, ‘B‘, 12)]
Пример № 6
для реверса сортировки в обратном порядке используется параметр
, reverse=True но поскольку его можно применить стазу ко всем выбранным ключам сортировки
print( sorted(student_objects, key=attrgetter('grade', 'age')), reverse = True) )
print( sorted(student_tuples, key=itemgetter(1, 2), reverse = True) )
, то чтобы можно было указать нужен ли реверс для конкретного ключа стоит сделать так:
from operator import itemgetter, attrgetter class Student: def __init__(self, name, grade, age): self.name = name self.grade = grade self.age = age def __repr__(self): return repr((self.name, self.grade, self.age)) student_objects = [ Student('john', 'A', 15), Student('jane', 'B', 12), Student('dave', 'B', 10) ] def multisort(xs, specs): for key, reverse in reversed(specs): xs.sort(key=attrgetter(key), reverse=reverse) return xs print( multisort(list(student_objects), (('grade', True), ('age', False))) )
((‘grade’, True), (‘age’, False)) в программе выше задана такая сортировка, т.е. для ключа ‘grade’ используем реверс (т.е. сортируем в обратном направлении), а для ключа ‘age’ реверс не используем.
Результат вывода:
[(‘dave’, ‘B’, 10), (‘jane’, ‘B’, 12), (‘john’, ‘A’, 15)]