Самый простой способ сортировки — использовать функцию 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']
В качестве другого примера, указание «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 , в которых используются сортировка и кортежи (в разделе «Основные упражнения »).