Сортировка Python

Самый простой способ сортировки — использовать функцию sorted(list), которая принимает список и возвращает новый список с элементами в отсортированном порядке. Исходный список не изменяется.

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

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

Функцию sorted() можно настроить с помощью необязательных аргументов. Необязательный аргумент sorted()verse=True, например sorted(list,verse=True), заставляет сортировать данные в обратном направлении.

  strs = ['aa', 'BB', 'zz', 'CC']
  print(sorted(strs))  ## ['BB', 'CC', 'aa', 'zz'] (case sensitive)
  print(sorted(strs, reverse=True))   ## ['zz', 'aa', 'CC', 'BB']

Пользовательская сортировка с ключом =

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

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

  strs = ['ccc', 'aaaa', 'd', 'bb']
  print(sorted(strs, key=len))  ## ['d', 'bb', 'ccc', 'aaaa']

вызов отсортирован с помощью ключа = len

В качестве другого примера, указание «str.lower» в качестве ключевой функции — это способ заставить сортировку обрабатывать прописные и строчные буквы одинаково:

  ## "key" argument specifying str.lower function to use for sorting
  print(sorted(strs, key=str.lower))  ## ['aa', 'BB', 'CC', 'zz']

Вы также можете передать свой собственный MyFn в качестве ключевой функции, например:

  ## Say we have a list of strings we want to sort by the last letter of the string.
  strs = ['xc', 'zb', 'yd' ,'wa']

  ## Write a little function that takes a string, and returns its last letter.
  ## This will be the key function (takes in 1 value, returns 1 value).
  def MyFn(s):
    return s[-1]

  ## Now pass key=MyFn to sorted() to sort by the last letter:
  print(sorted(strs, key=MyFn))  ## ['wa', 'zb', 'xc', 'yd']

Для более сложной сортировки, например сортировки по фамилии, а затем по имени, вы можете использовать функции itemgetter или attrgetter, например:

  from operator import itemgetter

  # (first name, last name, score) tuples
  grade = [('Freddy', 'Frank', 3), ('Anil', 'Frank', 100), ('Anil', 'Wang', 24)]
  sorted(grade, key=itemgetter(1,0))
  # [('Anil', 'Frank', 100), ('Freddy', 'Frank', 3), ('Anil', 'Wang', 24)]

  sorted(grade, key=itemgetter(0,-1))
  #[('Anil', 'Wang', 24), ('Anil', 'Frank', 100), ('Freddy', 'Frank', 3)]

метод сортировки()

В качестве альтернативы sorted() метод sort() списка сортирует этот список по возрастанию, например list.sort(). Метод sort() изменяет базовый список и возвращает None, поэтому используйте его следующим образом:

  alist.sort()            ## correct
  alist = blist.sort()    ## Incorrect. sort() returns None

Вышеупомянутое — очень распространенное недопонимание при использовании функции sort() — она *не возвращает* отсортированный список. Метод sort() необходимо вызывать для списка; она не работает ни с одной перечислимой коллекцией (но приведенная выше функция sorted() работает с чем угодно). Метод sort() предшествует функции sorted(), поэтому вы, скорее всего, увидите его в более старом коде. Методу sort() не требуется создавать новый список, поэтому он может работать немного быстрее, если элементы для сортировки уже находятся в списке.

Кортежи

Кортеж — это группа элементов фиксированного размера, например координата (x, y). Кортежи подобны спискам, за исключением того, что они неизменяемы и не меняют размер (кортежи не являются строго неизменяемыми, поскольку один из содержащихся в них элементов может быть изменяемым). Кортежи играют в Python своего рода «структурную» роль — удобный способ передачи небольшого логического набора значений фиксированного размера. Функция, которой необходимо возвращать несколько значений, может просто вернуть кортеж значений. Например, если бы я хотел иметь список трехмерных координат, естественным представлением Python был бы список кортежей, где каждый кортеж имеет размер 3 и содержит одну группу (x, y, z).

Чтобы создать кортеж, просто перечислите значения в круглых скобках, разделив их запятыми. «Пустой» кортеж — это просто пустая пара круглых скобок. Доступ к элементам кортежа аналогичен списку: len(), [ ], for, in и т. д. все работают одинаково.

  tuple = (1, 2, 'hi')
  print(len(tuple))  ## 3
  print(tuple[2])    ## hi
  tuple[2] = 'bye'  ## NO, tuples cannot be changed
  tuple = (1, 2, 'bye')  ## this works

Чтобы создать кортеж размера 1, после единственного элемента должна идти запятая.

  tuple = ('hi',)   ## size-1 tuple

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

Присвоение кортежа кортежу имен переменных идентичного размера присваивает все соответствующие значения. Если кортежи разного размера, выдается ошибка. Эта функция работает и для списков.

  (x, y, z) = (42, 13, "hike")
  print(z)  ## hike
  (err_string, err_code) = Foo()  ## Foo() returns a length-2 tuple

Список понятий (необязательно)

Понимание списков — это более продвинутая функция, которая удобна в некоторых случаях, но не нужна для упражнений и ее не нужно изучать сначала (т. е. вы можете пропустить этот раздел). Понимание списка — это компактный способ написания выражения, которое расширяется до целого списка. Предположим, у нас есть список чисел [1, 2, 3, 4], вот понимание списка для вычисления списка их квадратов [1, 4, 9, 16]:

  nums = [1, 2, 3, 4]

  squares = [ n * n for n in nums ]   ## [1, 4, 9, 16]

Синтаксис: [ expr for var in list ]for var in list выглядит как обычный цикл for, но без двоеточия (:). Выражение слева от него оценивается один раз для каждого элемента, чтобы получить значения для нового списка. Вот пример со строками, где каждая строка заменяется на верхний регистр с помощью '!!!' добавлено:

  strs = ['hello', 'and', 'goodbye']

  shouting = [ s.upper() + '!!!' for s in strs ]
  ## ['HELLO!!!', 'AND!!!', 'GOODBYE!!!']

Вы можете добавить проверку if справа от цикла for, чтобы сузить результат. Проверка if оценивается для каждого элемента, включая только те элементы, для которых проверка верна.

  ## Select values <= 2
  nums = [2, 8, 1, 6]
  small = [ n for n in nums if n <= 2 ]  ## [2, 1]

  ## Select fruits containing 'a', change to upper case
  fruits = ['apple', 'cherry', 'banana', 'lemon']
  afruits = [ s.upper() for s in fruits if 'a' in s ]
  ## ['APPLE', 'BANANA']

Упражнение: list1.py

Чтобы попрактиковаться в материале этого раздела, попробуйте решить последующие задачи в list1.py , в которых используются сортировка и кортежи (в разделе «Основные упражнения» ).