Ой, а также и гадость ...
print map $_->[1],
sort {
$a->[0] cmp $b->[0] ##first element of the array
or $a->[1] cmp $b->[1] }
map [ tr/"MATCH"/"MATCH"/, $_ ], @allmatches;
Часть sort
относительно прямолинейна.
sort { $a->[0] cmp $b->[0] or $a->[1] cmp $b->[1] } ...an array...
Каждый элемент массива сам является массивом refи сравнение выполняет сравнение строк (cmp
) первых элементов массива refs, и, если они равны (cmp
возвращает 0), вторых элементов.
Выходные данные отсортированымассив, следовательно.Это оставляет два куска кода для анализа.Первая строка и последняя строка.Последняя строка запускает map
:
map [ tr/"MATCH"/"MATCH"/, $_ ], @allmatches
Это, очевидно, выполняет преобразование без операции, поскольку левая и правая строки в операторе tr///
одинаковы;это немного озадачивает.[ Обновление : tr///
подсчитывает, сколько раз каждая из букв MATCH появляется в строке;внутри 'block' или 'expr' в map
, $_
есть специальная переменная - сопоставляемое значение.] Но он берет каждый элемент @allmatches
, отображает его и выводитиз этого передается в род.Квадратные скобки образуют массив ref, поэтому на выходе получается массив ссылок ref;каждая ссылка на массив содержит количество букв из слова MATCH в слове, за которым следует слово.
Первая строка:
print map $_->[1], ...output from sort...;
Это извлекает имя $_->[1]
из отсортированного вывода.
- В целом, эффект состоит в том, чтобы перечислить слова в
@allmatches
в таком порядке, чтобы слова с наименьшим (возможно, нулевым) буквой из MATCH появлялись первыми в алфавитном порядке.за ними следуют те, у которых следующие наименьшие буквы из MATCH (снова в алфавитном порядке) и т. д.
Это сжатие tour de force . Если бы кто-то предоставил мне его для обзора, он бы вернулся к чертежной доске. ( Обновление : так как это известная идиома ( преобразование Шварца * 1045)*), единственные причины для его отправки - «недостаточно тщательно изложены» и «не аннотированы как преобразование Шварца».)
# Schwartzian Transform: sort by number of letters from MATCH and alphabetically
print map { $_->[1] }
sort { $a->[0] <=> $b->[0] or $a->[1] cmp $b->[1] }
map { [ tr/"MATCH"/"MATCH"/, $_ ] }
@allmatches;
(Это правильно использует числовое сравнение для первого термина.)
Вы упоминаете, что были озадачены $a
и $b
.В основном это магические переменные - параметры функции сравнения в сортировке.Сравнение должно возвращать отрицательное значение, если $a
сравнивает меньше $b
, или положительное, если $a
сравнивает больше $b
, или ноль, если они сравниваются равными.Они ($a
и $b
) являются именами, используемыми, когда требуются два имени;$_
используется с map
(и grep
и другими функциями преобразования списка), где требуется только одно имя.