Разобраться с сортировкой и заполнить эту статью.
Примечание. Самая простая разница между 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)]