Быстрый в изучении - мощный в программировании
>> Telegram ЧАТ для Python Программистов

Свободное общение и помощь советом и решением проблем с кодом! Заходите в наш TELEGRAM ЧАТ!

>> Python Форум Помощи!

Мы создали форум где отвечаем на все вопросы связанные с языком программирования Python. Ждем вас там!

>> Python Канал в Telegram

Обучающие статьи, видео и новости из мира Python. Подпишитесь на наш TELEGRAM КАНАЛ!

6 примеров сортировки в Python с помощью функции sorted

Общей идиомой в программировании является сортировка списка. Python делает эту задачу очень простой благодаря встроенной функции sorted() которая принимает итерируемый тип и возвращает отсортированный список:

1. Стандартная сортировка

a = [3, 2, 5 ,4, 7, 1]
a = sorted(a)
 
print(a) # [1, 2, 3, 4, 5, 7]

Сортируем кортеж.

t = ('Zane', 'Bob', 'Janet')
t = sorted(t)
 
print(t) # ['Bob', 'Janet', 'Zane']

Сортировка словаря.

d = {1:'a', 2:'b', 3:'c'}
d = sorted(d)
print(d) # [1, 2, 3]

Обратите внимание на то, что функция sorted() возвращает список каждый раз, несмотря на то, какой тип был передан. В случае со словарями, она возвращает отсортированный список словарных ключей.

2. Сортировка сложных структур с использованием ключа

Это нормально работать с вещами, у которых по природе есть определенный порядок, вроде чисел или строк, но что делать с более сложными структурами? Здесь функция sorted() демонстрирует свое великолепие. Функция sorted() принимает ключ в качестве опционально названного параметра. Этот ключ должен быть, сам по себе, функцией, которая принимает один параметр, которая затем используется функцией sorted(), для определения значения в целях дальнейшей сортировки. Давайте взглянем на пример. Скажем, у нас есть класс Person с такими атрибутами как имя и возраст:

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    def __repr__(self):
        return "" % (self.name, self.age)

(Функция __repr__ является специальной функцией, которая используется для переопределения того, как объект будет представлен в интерпретаторе Python)

Причина, по которой я определил функцию – это выделение порядка сортировки. По умолчанию, представление определенных пользователем объектов выглядит примерно так: “<__main__.Person object at 0xb7083ccc>”. Если оставить все как есть, то отличать различные экземпляры в будущих примерах будет несколько затруднительно для нас.

Давайте сделаем список людей:

jack = Person('Jack', 19)
adam = Person('Adam', 43)
becky = Person('Becky', 11)
people = [jack, adam, becky]

Сама по себе функция sorted() не знает, что делать со списком людей:

a = sorted(people)
print(a) # [<name: Jack, age: 19>, <name: Adam, age: 43>, <name: Becky, age: 11>]

Однако, мы можем указать функции sorted(), какой атрибут сортировать, указав используемый ключ. Давайте определим это в следующем примере:

def byName_key(person):
    return person.name

Функция ключа должна принять один аргумент и выдать значение, на котором базируется сортировка. Функция sorted() должна вызвать функцию key в каждом элементе используемой итерируемой, и использовать значение выдачи при сортировке списка.

a = sorted(people, key = byName_key)
print(a) # [<name: Adam, age: 43>, <name: Becky, age: 11>, <name: Jack, age: 19>]

Обратите внимание на то, что мы передаем ссылку на саму функцию, не вызывая ее и передаем ссылку к её возвращаемому значению. Это очень важный момент. Помните, sorted() будет использовать функцию key, вызывая её в каждом элементе итерируемой.

Давайте взглянем на еще один код, на этот раз определяем возраст как значение для сортировки:

def byAge_key(person):
    return person.age
 
a = sorted(people, key = byAge_key)
print(a) # [<name: Becky, age: 11>, <name: Jack, age: 19>, <name: Adam, age: 43>]

3. Обратная сортировка

Функция sorted() намного упрощает сортировку в обратном порядке. Функция принимает опциональный параметр под названием reverse, который действует по строгой логике.

data = [3, 2, 5 ,4, 7, 1]
a = sorted(data, reverse = True)
print(a) # [7, 5, 4, 3, 2, 1]
 
data = ('Zane', 'Bob', 'Janet')
b = sorted(data, reverse = True)
print(b) # ['Zane', 'Janet', 'Bob']

4. Сортировка с использованием функции attrgetter

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

from operator import attrgetter

Результат вызова attrgetter() – это функция, схожая с предыдущими двумя, которые мы только что рассмотрели. Мы определяем имя атрибута для выборки, после чего attrgetter генерирует функцию, которая принимает объект и возвращает определенный атрибут из этого объекта.

getName = attrgetter('name')
result = getName(jack)
print(result) # 'jack'

Таким образом, attrgetter(name) возвращает функцию, которая ведет себя также как и определенная раннее нашей функцией byName_key():

result = sorted(people, key = attrgetter('name'))
print(result) # [<name: Adam, age: 43>, <name: Becky, age: 11>, <name: Jack, age: 19>]

Функция attrgetter(age) возвращает функцию, которая ведет себя также как и определенная раннее нашей функцией byAge_key():

result = sorted(people, key = attrgetter('age'))
print(result) # [<name: Becky, age: 11>, <name: Jack, age: 19>, <name: Adam, age: 43>]

5. Предварительное использование key в функции сортировки

До сих пор нашими ключевыми функциями были простые считыватели атрибутов, но они также могут вычислять значения для сортировки. Давайте взглянем на еще один пример. На этот раз мы определим класс Snake:

class Snake(object):
    def __init__(self, name, toxicity, aggression):
        self.name = name
        self.toxicity = toxicity
        self.aggression = aggression
    
    def __repr__(self):
        return "<%s>" % self.name

У нашей змеи есть имя, toxicity (токсичность, мерило того, насколько токсичен её яд) и agression (представленная в виде числа от 0 до 1, которое указывает на вероятность того, что змея нападет).

Надежный сайт по продвижению doctorsmm предлагает купить подписчиков на свой Телеграмм канал по очень выгодным и притягательным ценам от 51 рубля за сотню аккаунтов. Кроме того, Вы сможете подобрать наиболее оптимальную для Вашего сообщества скорость поступления, которая доходит до 1000 единиц в сутки.
gardenSnake = Snake('gardenSnake', 10, 0.1)
rattleSnake = Snake('rattleSnake', 100, 0.25)
kingCobra = Snake('kingCobra', 50, 1.0)
snakes = [rattleSnake, kingCobra, gardenSnake]

Теперь предположим, что мы можем подсчитать, насколько опасная змея, основываясь на показателях токсичности и агрессивности, и можем отсортировать список змей по степени их опасности:

def byDangerous_key(snake):
    return snake.toxicity * snake.aggression
 
result = sorted(snakes, key = byDangerous_key)
print(result) # [<gardenSnake>, <rattleSnake>, <kingCobra>]

Змеи отсортированы в ожидаемом нами порядке (несмотря на то, что гремучая змея (rattlesnake) более ядовита, чем кобра (kingCobra), уровень агрессивности кобры делает её более опасной).

6. Случайная сортировка

Ключи не обязаны иметь какую-либо связь с сортируемыми элементами (однако, это не самый продуктивный способ сортировать что-либо). Мы можем создать случайный порядок со следующим ключом:

from random import random
 
def randomOrder_key(element):
    return random()

Функция random() – это часть стандартной библиотеки random, которая выдает числа в случайном порядке от 0 до 1. Сортировка с использованием данного ключа выдает, кто бы мог подумать, случайный порядок:

a = sorted(snakes, key = randomOrder_key)
print(a) # [<kingCobra>, <gardenSnake>, <rattleSnake>]
 
b = sorted(snakes, key = randomOrder_key)
print(b) # [<rattleSnake>, <kingCobra>, <gardenSnake>]

В данной статье мы рассмотрели то, как Python создает отсортированные списки (и другие итерируемые) и то, насколько это просто. По умолчанию, функция sorted() возвращает список, содержимое которого упорядоченно в естественном порядке (что, в общем, именно то что мы ожидаем от чисел и строк). Желающие углубиться в то, как работает функция sorted() могут обратиться к документации Python.

Мы также научились определять наш собственный порядок сортировки, передавая функцию key функции sorted(). Наши ключевые функции могут возвращать любое значение, какое нам угодно, но зачастую нам, скорее всего, понадобится отсортировать атрибут, который принадлежит каждому элементу списка. Фактически, эта ситуация возникает настолько часто, что Python поместили функцию operator.getattr() в стандартную библиотеку, которая может генерировать ключевые функции этого типа для нас.

Комментариев: 9
  1. Сергей Ульянович | 2018-01-04 в 15:52:48

    Спасибо большое за статью! Очень интересно и познавательно.

    Единственный сайт где можно нормально изучать язык Python.

    Так держать, молодцы!

  2. Здравствуй Сергей!

    Заходи почаще.

    Как у тебя там с английским, все путем?

  3. А как быть если мы хоти отсортировать по двкм ключам?

    Допустим людей с одинаковым возрастом отсортировать по имени ?

  4. Здравствуйте, как написать программу котороя должна определить стоит ли список по убыванию и вывести на экран true or false, if it is true тогда сделать список по убыванию

  5. Спасибо !

    Отличный материал.

    Вопрос в 3.8 выдает ошибку -

    class Person(object):

    def __init__(self, name, age):

    self.name = name

    self.age = age

    def __repr__(self):

    return "" % (self.name, self.age)

    def byName_key(person):

    return person.name

    jack = Person('Jack', 19)

    adam = Person('Adam', 43)

    becky = Person('Becky', 11)

    people = [jack, adam, becky]

    a = sorted(people, key=byName_key)

    print(a)

    Консоль -

    Traceback (most recent call last):

    File "", line 22, in

    File "", line 7, in __repr__

    TypeError: not all arguments converted during string formatting

    ПиШарм -

    Traceback (most recent call last):

    File "C:/Users/User/PycharmProjects/WordDoc/sorted.py", line 22, in

    print(a)

    File "C:/Users/User/PycharmProjects/WordDoc/sorted.py", line 7, in __repr__

    return "" % (self.name, self.age)

    TypeError: not all arguments converted during string formatting

    Почему?

    Заранее спасибо.

  6. Официальное howto по сортировке в python на русском языке

    https://digitology.tech/docs/python_3/howto/sorting.html

  7. Народ помогите сделать задание из книги Эрика Мэтиза "Изучаем Python":

    "Используйте функцию sorted() для вывода списка в обратном алфавитном прядке без изменения порядка исходного списка."

    Итак, мой список:

    countrys = []

    countrys.append ('United States')

    countrys.append ('United Kingdom')

    countrys.append ('Denmark')

    countrys.append ('Australia')

    countrys.append ('Italy')

    print (countrys)

    #сортировка с изменением исходного списка у меня получается

    countrys = sorted(countrys, reverse=True)

    print (countrys)

    #а сортировку без изменения исходного списка не могу понять. Как ее сделать? Помогите пожалуйста!)

  8. Спасибо, помогло.

  9. Блин, спасибо