Функція sorted¶
Функція sorted повертає новий відсортований список елементів ітерованого об'єкта, який було передано як аргумент. Функція також підтримує додаткові параметри, які дозволяють контролювати сортування.
Синтаксис функції:
Перший аспект, на який важливо звернути увагу – sorted завжди повертає список, незалежно від типу даних, переданого як аргумент.
Наприклад, для таких даних:
list_of_words = ['one', 'two', 'list', '', 'dict']
tuple_of_words = ('one', 'two', 'list', '', 'dict')
set_of_words = {'one', 'two', 'list', '', 'dict'}
Результатом буде однаковий список:
In [4]: sorted(list_of_words)
Out[4]: ['', 'dict', 'list', 'one', 'two']
In [5]: sorted(tuple_of_words)
Out[5]: ['', 'dict', 'list', 'one', 'two']
In [6]: sorted(set_of_words)
Out[6]: ['', 'dict', 'list', 'one', 'two']
Сортування рядка:
In [7]: string_to_sort = 'long string'
In [8]: sorted(string_to_sort)
Out[8]: [' ', 'g', 'g', 'i', 'l', 'n', 'n', 'o', 'r', 's', 't']
Якщо передати sorted словник, функція поверне відсортований список ключів:
dict_for_sort = {
'id': 1,
'name': 'London',
'IT_VLAN': 320,
'User_VLAN': 1010,
'Mngmt_VLAN': 99,
'to_name': None,
'to_id': None,
'port': 'G1/0/11'
}
In [10]: sorted(dict_for_sort)
Out[10]:
['IT_VLAN',
'Mngmt_VLAN',
'User_VLAN',
'id',
'name',
'port',
'to_id',
'to_name']
reverse¶
Параметр reverse дозволяє керувати порядком сортування. За замовчуванням сортування буде за зростанням елементів.
Вказавши параметр reverse, можна змінити порядок:
In [11]: list_of_words = ['one', 'two', 'list', '', 'dict']
In [12]: sorted(list_of_words)
Out[12]: ['', 'dict', 'list', 'one', 'two']
In [13]: sorted(list_of_words, reverse=True)
Out[13]: ['two', 'one', 'list', 'dict', '']
key¶
ітерованого об'єкта
За допомогою параметра key можна вказувати, як саме сортувати елементи. Параметр key очікує функцію яка приймає один аргумент. Функція використовується для отримання ключа порівняння з кожного елемента ітерованого об'єкта. Значення за замовчуванням — None (порівнюються безпосередньо елементи).
Наприклад, таким чином можна відсортувати список рядків за довжиною рядка:
In [14]: list_of_words = ['one', 'two', 'list', '', 'dict']
In [15]: sorted(list_of_words, key=len)
Out[15]: ['', 'one', 'two', 'list', 'dict']
Якщо потрібно відсортувати список рядків, але ігнорувати регістр рядків, можна створити функцію, яка переводить рядок у нижній регістр і використати її в key:
def to_lower(string):
return string.lower()
words = ['id', 'name', 'IT_VLAN', 'User_VLAN', 'Mngmt_VLAN', 'to_name', 'port']
In [6]: sorted(words, key=to_lower)
Out[6]: ['id', 'IT_VLAN', 'Mngmt_VLAN', 'name', 'port', 'to_name', 'User_VLAN']
Такий самий результат можна отримати з використанням методу lower:
In [7]: sorted(words, key=str.lower)
Out[7]: ['id', 'IT_VLAN', 'Mngmt_VLAN', 'name', 'port', 'to_name', 'User_VLAN']
За допомогою параметра key можна сортувати об'єкти не за першим елементом, а за будь-яким іншим. Але для цього треба створити додаткову функцію або використовувати функцію lambda або спеціальні функції з модуля operator.
Наприклад, щоб відсортувати список кортежів із двох елементів за другим елементом, можна використовувати такий прийом:
from operator import itemgetter
list_of_tuples = [
('IT_VLAN', 320),
('Mngmt_VLAN', 99),
('User_VLAN', 1010),
('DB_VLAN', 11)
]
In [2]: sorted(list_of_tuples, key=itemgetter(1))
Out[2]: [('DB_VLAN', 11), ('Mngmt_VLAN', 99), ('IT_VLAN', 320), ('User_VLAN', 1010)]
Приклад сортування різних об'єктів¶
Сортування виконується за першим елементом, наприклад, за першим символом у списку рядків, якщо він збігається, за другим і так далі. Сортування виконується за кодом Unicode символу.
Приклад сортування списку рядків:
In [6]: data = ["test1", "test2", "text1", "text2"]
In [7]: sorted(data)
Out[7]: ['test1', 'test2', 'text1', 'text2']
Деякі дані будуть сортуватися "неправильно", наприклад, список IP-адрес:
In [11]: ip_list = ["10.1.1.1", "10.1.10.1", "10.1.2.1", "10.1.11.1"]
In [12]: sorted(ip_list)
Out[12]: ['10.1.1.1', '10.1.10.1', '10.1.11.1', '10.1.2.1']
Таке сортування називається лексикографічним. Щоб у цьому випадку сортування було нормальним, треба або використовувати окремий модуль з натуральним сортуванням (модуль natsort) або сортувати, наприклад, за двійковим/десятковим значенням адреси.
Приклад сортування IP-адрес за двійковим значенням. Спочатку створюємо функцію, яка перетворює IP-адреси на двійковий формат:
def bin_ip(ip):
octets = [int(octet) for octet in ip.split(".")]
return "{:08b}{:08b}{:08b}{:08b}".format(*octets)
In [16]: bin_ip("10.1.1.1")
Out[16]: '00001010000000010000000100000001'
In [17]: bin_ip("160.1.1.1")
Out[17]: '10100000000000010000000100000001'
Сортування за допомогою функції bin_ip:
In [18]: ip_list = ["10.1.1.1", "10.1.10.1", "10.1.2.1", "10.1.11.1"]
In [19]: sorted(ip_list, key=bin_ip)
Out[19]: ['10.1.1.1', '10.1.2.1', '10.1.10.1', '10.1.11.1']
Note
Також далі розглядатиметься модуль ipaddress, який дозволить створювати спеціальні об'єкти, які відповідають IP-адресі і вони вже сортуються правильно за десятковим значенням.