Возможности и примеры функции sorted в Python

Функция sorted() возвращает новый отсортированный список итерируемого объекта (списка, словаря, кортежа). По умолчанию она сортирует его по возрастанию.

Сортировка строк осуществляется по ASCII-значениям.

  • Возвращаемое значение — List (список).
  • Синтаксис: sorted(iterable,key=None,reverse=False).
  • iterable: строка, список, кортеж, множество, словарь
  • key (необязательный параметр): если указать ключ, то сортировка будет выполнена по функции этого ключа.
  • reverse (необязательный параметр): по умолчанию сортировка выполняется по возрастанию. Если указать reverse=True, то можно отсортировать по убыванию.

# Сортировка строки
s2="hello"
print(sorted(s2)) # Вывод:['e', 'h', 'l', 'l', 'o']
print(sorted(s2, reverse=True)) # Вывод:['o', 'l', 'l', 'h', 'e']

# Сортировка списка
l1=[1, 4, 5, 2, 456, 12]
print(sorted(l1)) # Вывод:[1, 2, 4, 5, 12, 456]
print(sorted(l1, reverse=True)) # Вывод:[456, 12, 5, 4, 2, 1]

# Сортировка кортежа
t1=(15, 3, 5, 7, 9, 11, 42)
print(sorted(t1)) # Вывод:[3, 5, 7, 9, 11, 15, 42]
print(sorted(t1, reverse=True)) # Вывод:[42, 15, 11, 9, 7, 5, 3]

# Сортировка списка кортежей
t2=[(1, 2), (11, 12), (0, 2), (3, 2)]
print(sorted(t2)) # Вывод:[(0, 2), (1, 2), (3, 2), (11, 12)]
print(sorted(t2, reverse=True)) # Вывод:[(11, 12), (3, 2), (1, 2), (0, 2)]

# Сортировка множества
s1={1, 4, 3, 6, 2, 8, 11, 32}
print(sorted(s1)) # Вывод:[1, 2, 3, 4, 6, 8, 11, 32]
print(sorted(s1, reverse=True)) # Вывод:[32, 11, 8, 6, 4, 3, 2, 1]

# Сортировка словаря
d1={2: 'red', 1: 'green', 3: 'blue'}
# Вернется список отсортированных ключей
print(sorted(d1)) # Вывод:[1, 2, 3]

# Вернется список отсортированных значений
print(sorted(d1.values())) # Вывод:['blue', 'green', 'red']

# Вернется список кортежей (ключ, значение), отсортированный по ключам.
print(sorted(d1.items())) # Вывод:[(1, 'green'), (2, 'red'), (3, 'blue')]

# Сортировка словаря в обратном порядке
print(sorted(d1, reverse=True)) # Вывод:[3, 2, 1]
print(sorted(d1.values(), reverse=True)) # Вывод:['red', 'green', 'blue']
print(sorted(d1.items(), reverse=True)) # Вывод:[(3, 'blue'), (2, 'red'), (1, 'green')]

Параметр key

Итерируемый объект можно также отсортировать по функции, указанной в параметре key. Это может быть:

  • Встроенная функция,
  • Определенная пользователем функция,
  • Лямбда-функция,
  • itemgetter,
  • attrgetter.

1. Встроенная функция

len()— посчитает длину объекта. Если указать len в виде параметра key, то сортировка будет выполнена по длине.


# Сортировка словаря на основе функции len
l1 = {'carrot': 'vegetable', 'red': 'color', 'apple': 'fruit'}
# Возвращает список ключей, отсортированных по функции len
print(sorted(l1, key=len))
# Вывод: ['red', 'apple', 'carrot']

# Возвращает список значений, отсортированных на основе функции len
print(sorted(l1.values(), key=len))
# Вывод: ['fruit', 'color', 'vegetable']

# Сортировка списка на основе функции len
l1 = ['blue', 'green', 'red', 'orange']
print(sorted(l1, key=len))
# Вывод: ['red', 'blue', 'green', 'orange']

abs() вернет абсолютно значение числа. Если задать abs для key, то сортировка будет основана на абсолютном значении.


# Сортировка списка по абсолютному значению
l1 = [1, -4, 5, -7, 9, 2]
print(sorted(l1, key=abs))
# Вывод: [1, 2, -4, 5, -7, 9]

str.lower() — конвертирует все символы в верхнем регистре в нижний регистр. В таком случае список будет отсортирован так, будто бы все символы в нижнем регистре.


s1 = "Hello How are you"

# Разбивает строку и сортирует по словам
print(sorted(s1.split()))
# Вывод: ['Hello', 'How', 'are', 'you']

# Разбивает строку и сортирует после применения str.lower ко всем элементам
print(sorted(s1.split(), key=str.lower))
# Вывод: ['are', 'Hello', 'How', 'you']

d1 = {'apple': 1, 'Banana': 2, 'Pears': 3}
# Возвращает список ключей, отсортированный по значениям
print(sorted(d1))
# Вывод: ['Banana', 'Pears', 'apple']

# Возвращает список ключей, отсортированный после применения str.lower ко всем элементам
print(sorted(d1, key=str.lower))
# Вывод: ['apple', 'Banana', 'Pears']

2. Пользовательские функции

Также можно указывать свои функции.

Пример №1: по умолчанию сортировка кортежа происходит по первому элементу в нем. Добавим функцию, которая будет возвращать второй элемент кортежа. Теперь и сортировка будет опираться на соответствующий элемент.


# напишем функцию для получения второго элемента
def sort_key(e):
return e[1]

l1 = [(1, 2, 3), (2, 1, 3), (11, 4, 2), (9, 1, 3)]
# По умолчанию сортировка выполняется по первому элементу
print(sorted(l1))
# Вывод: [(1, 2, 3), (2, 1, 3), (9, 1, 3), (11, 4, 2)]

# Сортировка по второму элементу с помощью функции sort_key
print(sorted(l1, key=sort_key))
# Вывод: [(2, 1, 3), (9, 1, 3), (1, 2, 3), (11, 4, 2)]

Пример №2: можно сортировать объекты класса с помощью функций. Вот как это происходит:

  • У класса Studen есть три атрибута: name, rollno, grade.
  • Создаются три объекта этого класса: s1, s2, s3.
  • Создается список s4, который содержит все три объекта.
  • Дальше происходит сортировка по этому списку.
  • Определенная функция (sort_key) возвращает атрибут rollno.
  • В функции sorted эта функция задана для параметра key.
  • Теперь sorted() возвращает список объектов Student, которые отсортированы по значению rollno.

class Student:
def __init__(self, name, rollno, grade):
self.name = name
self.rollno = rollno
self.grade = grade

def __repr__(self):
return f"{self.name}-{self.rollno}-{self.grade}"

# Создание объектов
s1 = Student("Paul", 15, "second")
s2 = Student("Alex", 12, "fifth")
s3 = Student("Eva", 21, "first")
s4 = [s1, s2, s3]

# Сортировка списка объектов
# Создание функции, которая вернет rollno объекта
def sort_key(s):
return s.rollno

# сортировка списка объектов без ключевого параметра, вызывает TypeError
print(sorted(s4))
# Вывод: TypeError: '>' not supported between instances of 'Student' and 'Student'

# Сортировка списка объектов по атрибуту: rollno
s5 = sorted(s4, key=sort_key)
print(s5)
# Вывод: [Alex-12-fifth, Paul-15-second, Eva-21-first]

3. Лямбда-функция

Также в качестве ключа можно задать лямбда-функцию. Сортировка будет выполняться по ней.

Пример №1: сортировка списка объектов класса на основе лямбда-функции, переданной для параметра key.


class Student:
def __init__(self, name, rollno, grade):
self.name = name
self.rollno = rollno
self.grade = grade

def __repr__(self):
return f"{self.name}-{self.rollno}-{self.grade}"

# Создание объектов
s1 = Student("Paul", 15, "second")
s2 = Student("Alex", 12, "fifth")
s3 = Student("Eva", 21, "first")
s4 = [s1, s2, s3]

# Сортировка списка объектов
# Создание lambda-функции, которая вернет rollno объекта
s5 = sorted(s4, key=lambda x: x.rollno)
print(s5)
# Вывод: [Alex-12-fifth, Paul-15-second, Eva-21-first]

Пример №2: сортировка кортежей по второму элементу. Лямбда-функция просто возвращает его для каждого переданного объекта.


l1 = [( 1, 2, 3), (3, 1, 1), (8, 5, 3), (3, 4, 2)]

# Сортировка по второму элементу в кортеже.
# Lambda-функция возвращает второй элемент в кортеже.
print(sorted(l1, key=lambda x: x[1]))
# Вывод: [(3, 1, 1), (1, 2, 3), (3, 4, 2), (8, 5, 3)]

4. itemgetter

operator — это встроенный модуль, включающий много операторов. itemgetter(n) создает функцию, которая принимает итерируемый объект (список, кортеж, множество) и возвращает n-элемент из него.

Пример №1: сортировка списка кортежей по третьему элементу в каждом из них. itemgetter() возвращает функцию, которая получает третий элемент в кортеже. По умолчанию если key не указать, то сортировка будет выполнена по первому элементу кортежа.


from operator import itemgetter

l1 = [(1, 2, 3), (3, 1, 1), (8, 5, 3), (3, 4, 2)]

# Сортировка по третьему элементу в кортеже
print(sorted(l1, key=itemgetter(2)))
# Вывод: [(3, 1, 1), (1, 2, 3), (3, 4, 2), (8, 5, 3)]

Пример №2: сортировка списка словарей по ключу age.


from operator import itemgetter

# Создание списка словарей
d1 = [{'name': 'Paul', 'age': 30},
{'name': 'Alex', 'age': 7},
{'name': 'Eva', 'age': 3}]

# Сортировка по key(age) в словаре
print(sorted(d1, key=itemgetter('age')))
# Вывод: [{'name': 'Eva', 'age': 3}, {'name': 'Alex', 'age': 7}, {'name': 'Paul', 'age': 30}]

Пример №3: сортировка значений словаря с помощью itemgetter.


from operator import itemgetter

d = {'a': [1, 2, 3], 'b': [3, 4, 5], 'c': [1, 1, 2]}
print(sorted(d.values(), key=itemgetter(1)))
# Вывод: [[1, 1, 2], [1, 2, 3], [3, 4, 5]]

5. attrgetter

operator.attrgetter(attr)
operator.attrgetter(*attrs)

Возвращает вызываемый объект, который получает attr операнда. Если требуется больше одного аргумента, то возвращается кортеж атрибутов. Названия также могут включать троеточия.

Пример: сортировка списка объекта классов с помощью attrgetter. Функция attrgetter может получить атрибут объекта, а функция sorted будет выполнять сортировку на основе этого атрибута.


from operator import attrgetter

class Student:
def __init__(self, name, rollno, grade):
self.name = name
self.rollno = rollno
self.grade = grade

def __repr__(self):
return f"{self.name}-{self.rollno}-{self.grade}"

# Создание объектов
s1 = Student("Paul", 15, "second")
s2 = Student("Alex", 12, "fifth")
s3 = Student("Eva", 21, "first")
s4 = [s1, s2, s3]

# Сортировка списка объектов по атрибуту: rollno
s5 = sorted(s4, key=attrgetter('rollno'))
print(s5)
# Вывод: [Alex-12-fifth, Paul-15-second, Eva-21-first]

Многоуровневая сортировка

  • С помощью itemgetter можно также выполнять сортировку на нескольких уровнях.

В следующем примере сортировка значений словаря будет выполнена по второму элементу. Если же некоторые из них будут равны, то сортировка пройдет по третьему элементу.


from operator import itemgetter

d = {'a': [1, 2, 9], 'b': [3, 2, 5], 'c': [1, 1, 2]}

# Сортировка по второму, затем по третьему элементу
print(sorted(d.values(), key=itemgetter(1, 2)))
# Вывод: [[1, 1, 2], [3, 2, 5], [1, 2, 9]]
  • Многоуровневая сортировка с помощью лямбда-функции в key.

А в этом примере сортировка кортежа будет проходить по второму элементу. В случае равенства используется третий.


l1 = [(1, 2, 3), (4, 2, 0), (2, 1, 7)]
# Сортировка по второму элементу
# Если второй элемент равен, сортировка по третьему элементу.
print(sorted(l1, key=lambda x: x[1:3]))

Сортировка смешанных типов данных

Функция sorted не поддерживает смешанные типы данных. При попытке выполнить сортировку она вернет ошибку TypeError.


# список, содержащий смешанные типы данных
l1 = [1, 'a', 2]
print(sorted(l1))
# Вывод: TypeError: '>' not supported between instances of 'str' and 'int'

Выводы

  1. При сортировке списка объектов класса параметр key является обязательным. Если его не указать, то вернется ошибка TypeError.
  2. Для сортировки списка объектов класса можно использовать в качестве параметра key определенную пользователем функцию, лямбда-функцию или attrgetter.
  3. Функция sorted() возвращает список.
  4. Метода sort отсортирует сам оригинальный список. Но функция sorted возвращает новый список, не изменяя оригинальный.
  5. Метод sort используется только для сортировки списка. Его нельзя использовать для строки, кортежа или словаря.