Олег Алистратов — Сортировка списков в Perl и Python
description
Transcript of Олег Алистратов — Сортировка списков в Perl и Python
![Page 1: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/1.jpg)
Олег Алистратов
Руководитель группы разработки OTRS
Сортировка списков в Perl и Python
Я.Субботник, Екатеринбург
6 июля 2013 года
![Page 2: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/2.jpg)
2
result = sorted(unsorted)
unsorted.sort()
Основы Python
my @sorted = sort @unsorted;
Perl
![Page 3: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/3.jpg)
3
Универсальные алгоритмы
1. Сравнить два элемента
2. Переставить два элемента
![Page 4: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/4.jpg)
4
Функция сравнения
• Принимает два элемента
• Возвращает целое число:
– < 0, если первый элемент меньше второго
– 0, если элементы равны
– > 0, если первый элемент больше второго
![Page 5: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/5.jpg)
5
Если список содержит NaN, результат сортировки не определен.
>>> sorted([1, float('NaN'), 0])
[1, nan, 0]
Списки, содержащие NaN
![Page 6: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/6.jpg)
6
import math
clean = filter(lambda x: not math.isnan(x), mixed)
Удаление NaN из списков Python
@clean = grep { $_ == $_ } @mixed;
Perl
![Page 7: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/7.jpg)
Joseph Hall
“OR” + “cache” = “Orcish” —
pronounced the same way a reader of
Tolkien literature would say it.
Orcish Maneuver (OM)
![Page 8: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/8.jpg)
8
def compare_mtime(a, b):
return cmp(os.path.getmtime(a), os.path.getmtime(b))
sorted(files, cmp=compare_mtime)
Сортировка файлов по времени модификации
Python
sort { -M $a <=> -M $b } @files;
Perl
![Page 9: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/9.jpg)
Всё, что происходит в
функции сравнения,
происходит O(n logn) раз.
![Page 10: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/10.jpg)
10
def cmp_cached(a, b):
if a not in cache:
cache[a] = os.path.getmtime(a)
if b not in cache:
cache[b] = os.path.getmtime(b)
return cmp(cache[a], cache[b])
sorted(files, cmp=cmp_cached)
Кеширование ключей
Python
my %cache;
my @sorted = sort {
( $cache{$a} //= -M $a )
<=>
( $cache{$b} //= -M $b )
} @files;
Perl
![Page 11: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/11.jpg)
Decorate-Sort-Undecorate
Schwartzian transform (ST)
![Page 12: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/12.jpg)
Сохранение ключа с данными
1. [ "abc", "de", "fghi", "k" ]
2. [ (3, "abc"), (2, "de"), (4, "fghi"), (1, "k") ]
3. [ (1, "k"), (2, "de"), (3, "abc"), (4, "fghi") ]
4. [ "k", "de", "abc", "fghi" ]
![Page 13: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/13.jpg)
13
decorated = [ (calckey(x), x ) for x in data ]
decorated.sort()
result = [ x for k, x in decorated ]
ST в действии
Python
my @s = map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
map { [calckey(@$_), $_] }
@list;
Perl
![Page 14: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/14.jpg)
14
Функция sorted() принимает параметр key – и делает ST за вас.
sorted(os.listdir('/'), key=lambda x: os.path.getmtime(x))
ST в Python
![Page 15: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/15.jpg)
15
operator.itemgetter(), operator.attrgetter()
sorted(
goods,
key=operator.attrgetter('price'),
reverse=True
)
Сортировка по полям
![Page 16: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/16.jpg)
16
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
ST
OM
key
cmp
Python Perl
Производительность пользовательской функции сравнения, OM и ST
![Page 17: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/17.jpg)
Guttman-Rosler Transform (GRT)
![Page 18: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/18.jpg)
18
Кортежи из трех целых чисел в диапазоне [ 0, 99 ]
[
( 8, 85, 27),
(41, 65, 81),
(51, 66, 75),
(17, 71, 84),
(41, 13, 91),
...
]
Исходные данные
![Page 19: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/19.jpg)
19
def unpack(a):
x = int(a / 100**2)
y = int(a / 100) - x * 100
z = 99 - a % 100
return (x, y, z)
def pack(s):
return s[0] * 100**2 + s[1] * 100 + 99 - s[2]
map(unpack, sorted(map(pack, data)))
Арифметическое кодирование
Python
my @s = map
{
my $x = int($_ / 100**2);
my $y = int($_ / 100) - $x * 100;
my $z = 99 - $_ % 100;
[ $x, $y, $z ];
}
sort { $a <=> $b }
map { $_->[0] * 100**2 + $_->[1] * 100 + 99 - $_->[2] }
@data;
Perl
![Page 20: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/20.jpg)
20
def unpack(a):
return (ord(a[0]), ord(a[1]), 99 - ord(a[2]))
def pack(s):
return chr(s[0]) + chr(s[1]) + chr(99 - s[2])
map(unpack, sorted(map(pack, data)))
Кодирование в строки
Python
my @s = map { [ unpack "C3", $_ ] }
sort
map { pack "C3", @$_ }
@data;
Perl
![Page 21: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/21.jpg)
21
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
битовые поля
кодирование в строки
арифметическое кодирование
itemgetter
cmp
Python Perl
Производительность пользовательской функции сравнения и GRT
![Page 22: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/22.jpg)
Сериализация
• Запись в битовые поля
• Арифметическое кодирование
• Формирование строк фиксированной длины
(padding)
• Формирование строк с разделителями
(например, нулевыми байтами)
![Page 23: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/23.jpg)
Модули и библиотеки
![Page 24: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/24.jpg)
CPAN
• Sort::Maker
• Sort::MultipleFields
• Sort::Key
• Sort::Fields
• Sort::XS
• Sort::External
![Page 25: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/25.jpg)
25
Прагма sort позволяет узнавать и выбирать алгоритм сортировки.
use sort qw(stable);
use sort
![Page 26: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/26.jpg)
numpy.sort, numpy.lexsort
• Выбор алгоритма сортировки
• Сортировка многомерных массивов
• Сортировка по нескольким полям
• Поиск в упорядоченных списках
![Page 27: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/27.jpg)
Заключение
• Функция сравнения вызывается O(n logn) раз
• Сохраняйте ключи сортировки
• Упакуйте элементы списка в числа или строки
и сравнивайте их одной операцией
• Пользуйтесь готовым
![Page 28: Олег Алистратов — Сортировка списков в Perl и Python](https://reader033.fdocument.pub/reader033/viewer/2022051313/549000ddb4795956138b4f73/html5/thumbnails/28.jpg)
Исходные тексты
https://github.com/alistratov/articles/tree/master/sorting/benchmarks