Если нужно упорядочить список другим образом, то нужно в качестве первого аргумента функции указать блок, выполняющий сравнение двух элементов сортируемого списка и возвращающий значения -1, 0, 1 - они означают, что первый элемент меньше, равен или больше второго. При сравнении чисел это проще всего сделать с помощью операции <=>, например:
@sorted = sort {$a <=> $b } @unsorted;
# в @sorted будет (1, 2, 3, 12, 25, 53, 128, 400)
В блоке сравнения переменные $a и $b содержат значения двух текущих сравниваемых элементов. Для выполнения сортировки по убыванию достаточно поменять переменные местами {$b <=> $a }. Помните, что для сортировки в обратном порядке строковых значений нужно применить операцию сравнения строк {$b cmp $a }. Вместо блока можно вызвать пользовательскую подпрограмму, выполняющую сколь угодно сложные сравнения элементов сортируемого списка.
Перестановку всех элементов списка в обратном порядке выполняет встроенная функция reverse, возвращающая инвертированный список, не меняя исходного:
@array = qw(Do What I Mean); # исходный список
@backwards = reverse @array; # остается неизменным
# в @backwards будет ('Mean', 'I', 'What', 'Do')
Вложенный вызов функций позволяет сначала отсортировать список, а потом переставить элементы в обратном порядке:
@backwards = reverse(sort(@array));
# в @backwards будет ('What', 'Mean', 'I', 'Do')
Обратите внимание, что во всех приведенных примерах по желанию программиста аргументы функций можно указывать в круглых скобках, но делать это не обязательно. Имея в своем распоряжении мощные примитивы для работы с массивами, подобные reverse или splice, программист может легко решать весьма нетривиальные задачи. Это подтверждает короткая программа на Perl, выполняющая циклический сдвиг массива тремя вызовами функции reverse:
my @array = qw/Н А Ч А Л О К О Н Е Ц/; # исходный массив
my $i = 3; # сдвиг массива ВЛЕВО на 3 элемента
my $n = @array; # число элементов массива
# алгоритм сдвига Кена Томпсона (1971)
@array[0 ..$i-1] = reverse @array[0 .. $i-1];
@array[$i .. $n-1] = reverse @array[$i .. $n-1];
@array[0 .. $n-1] = reverse @array[0 .. $n-1];
print "@array\n"; # результат: А Л О К О Н Е Ц Н А Ч
Функция map позволяет выполнить действия над всеми элементами массива, поэтому ее нередко используют вместо цикла. У этой функции есть две формы вызова:
@result = map ВЫРАЖЕНИЕ, СПИСОК
@result = map БЛОК СПИСОК
Она вычисляет выражение или блок для каждого элемента списка и возвращает список результатов. С ее помощью, например, можно выполнить арифметическое действие над всеми элементами списка:
@result = map $_*10, (11, 32, 55); # работа со списком
# в @result будет (110, 320, 550)
При работе map специальная переменная $_ локально устанавливается как синоним текущего элемента списка, поэтому изменение переменной $_ приводит к изменению соответствующего элемента массива. Таким способом можно изменять значения элементов массива. В этом примере воспользуемся блоком, куда поместим операторы вычисления нового значения (если значение элемента больше 20, оно будет удесятеряться):
@array = (11, 32, 55); # исходный массив
@result = map {if ($_ > 20) {$_*=10;} else {$_;} } @array;
# в @result будет (11, 320, 550)
Список можно преобразовать в строку с помощью встроенной функции join, которая преобразует каждый элемент списка к строке, объединяет отдельные элементы списка в одну строку, вставляя между элементами указанный разделитель, и возвращает полученную строку в качестве результата. Например:
@array = (5..10); # объединяемый список
$delimiter = ':'; # разделитель элементов списка в строке
$string = join $delimiter, @array; # объединение в строку
# теперь $string содержит '5:6:7:8:9:10'
Обратную операцию разделения строки по образцу на список строк выполняет встроенная функция split. Она разделяет строку по указанному разделителю и возвращает список составляющих строк. Можно ограничить число разделяемых подстрок, тогда строка будет разделена не более, чем на это число элементов. Например:
$string = '5:6:7:8:9:10'; # исходная строка
$delimiter = ':'; # разделитель подстрок
$limit = 3; # число элементов
@strings = split $delimiter, $string, $limit; # разделение
# в @strings содержится ('5', '6', '7:8:9:10')
Функция split имеет гораздо больше возможностей, о которых будет сказано в лекции, посвященной регулярным выражениям. Подробно познакомиться с которыми можно из системной документации с помощью утилиты perldoc (после флага -f указывается имя искомой функции):