@deleted = splice @array, $offset, $size, qw(новый список);
# в @array теперь (1, 2, 'новый', 'список', 7)
# в @deleted попали 4 удаленных элемента (3, 4, 5, 6)
Если список для вставки не указан, то подсписок от элемента с индексом $offset в количестве $size элементов просто удаляется.
Операция сортировки списка выполняется встроенной функцией sort, которая, не изменяя своего аргумента, возвращает список, отсортированный по возрастанию строковых значений элементов исходного списка. Поясним на примере:
@unsorted = (12, 1, 128, 2, 25, 3, 400, 53);
@sorted = sort @unsorted;
# в @sorted будет (1, 12, 128, 2, 25, 3, 400, 53)
Если нужно упорядочить список другим образом, то нужно в качестве первого аргумента функции указать блок, выполняющий сравнение двух элементов сортируемого списка и возвращающий значения -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 указывается имя искомой функции):
perldoc -f split
Пользовательские функции и процедуры, как встроенные функции, тоже могут обрабатывать списки: принимать списки параметров и возвращать список значений. Об этом будет подробнее рассказано в лекции 12.