При работе с массивом иногда необходимо выделять из него некоторое подмножество элементов,
которое будем называть фрагментом массива. Фрагмент может содержать как последовательные элементы
массива, так и просто отдельные элементы массива. Последовательность элементов во фрагменте может
быть произвольной. Для выполнения поставленной задачи язык Perl предлагает специальную
синтаксическую конструкцию. Если после имени массива в квадратных скобках задать некоторый список
целых чисел, представляющих индексы некоторых элементов массива, то такая конструкция и будет
означать выделение фрагмента массива, состоящего из указанных элементов исходного массива.
Несколько примеров создания фрагментов массива представлены ниже.
@аrrау = ("a".."g"); # Исходный массив:
# а, b, с, d, e, f, g
@аrray[0, 3, 5] # Фрагмент: a, d, f
@array[5, 1..2] # Фрагмент: f, b, c
@array[-l, 1..2, -2] # Фрагмент: g, b, с, f
Стандартные функции обработки массивов скаляров
В языке Perl определен ряд стандартных функций для добавления и удаления элементов из
массива скаляров.
Две функции —
pop и
shift —
удаляют из массива скаляров соответственно последний и первый
элемент и возвращают его значение. После удаления первого элемента массива функцией shift
оставшиеся сдвигаются влево, что уменьшает на единицу индекс, по которому можно ссылаться на
эти элементы. Удаление функцией pop последнего элемента массива также приводит к уменьшению
на единицу индекса массива. Если переданный в качестве параметра в эти функции массив пуст,
то обе функции возвращают неопределенное значение
undef.
Эти функции можно использовать вообще без параметра. В этом случае, если они используются
в основной программе, то в качестве параметра используется специальный массив @ARGV, что
позволяет последовательно получать переданные в сценарий из командной строки параметры в
прямом или обратном порядке. Если функции используются в пользовательской подпрограмме, то
они работают со специальным массивом @_, с помощью которого передаются фактические параметры
в подпрограмму при ее вызове.
Функции
push и
unshift
соответственно добавляют в конец или в начало массива список
значений в порядке их задания, возвращая новое количество элементов в массиве скаляров.
Обращение к этим функциям требует задания двух фактических параметров: имени массива и списка
добавляемых значений элементов.
Удалить определенное количество элементов после элемента с заданным порядковым номером в
массиве можно функцией splice со следующим синтаксисом:
splice МАССИВ, НОМЕР [, КОЛИЧЕСТВО];
Если количество элементов не задано, то удаляются все элементы, расположенные в массиве
после элемента с указанным порядковым номером, причем так же, как и в случае с функцией shift,
индексы оставшихся элементов переформируются в непрерывную последовательность.
ВНИМАНИЕ. В функции splice задается порядковый номер элемента массива, а не его индекс.
Если последним, четвертым параметром задан список скалярных значений, то указанные элементы
массива не удаляются, а их значения меняются на значения, определенные в списке.
Фрагмент программы, использующей перечисленные функции, приведен ниже:
@array = ("first", "last");
push @array "a", "b"; # Массив @array содержит:
# "first", "last", "a", "b"
splice @array, 2; # Удаление добавленных элементов
# "a" и "b"
unshift @array, "a", "b"; # Массив @array содержит:
# "a", "b", "first", "last"
Начиная с версии Perl 5.6.0 удалить элементы из массива скаляров можно функцией delete( ),
которая в предыдущих версиях использовалась только для работы с элементами хэш-массивов.
Параметром этой функции является элемент или фрагмент массива скаляров, а возвращаемым значением –
значение удаленного элемента или список значений удаленных элементов в случае фрагмента массива.
Удаление с помощью этой функции возвращает указанные в ее параметре элементы массива (если только
они не являются концевыми) в первоначальное, неинициализированное состояние и не производит
никаких преобразований индексов оставшихся элементов, то есть удаленные элементы остаются в
массиве, но их значения становятся неопределенными undef.
Функцию
exists( )
также начиная с версии Perl 5.6.0 можно применять к массивам скаляров для
определения существования элемента с указанным индексом. Она возвращает значение «истина»,
если элементу массива присваивалось значение, даже неопределенное undef, и «ложь» в противном
случае, когда элемент массива не инициализирован, удален функцией
delete( )
или вообще не существует.
Следующий фрагмент кода Perl-программы демонстрирует применение функций exists( ) и delete( )
к массиву скаляров:
@array = ("first", 2, "third");
@array[9] = 9;
@array[7] = undef;
$ind = 7;
# Печать будет выполнена, элемент инициализирован
print "Элемент $ind существует\n" if exists @array[$ind];
$ind=8;
# Печать будет выполнена, элемент не инициализирован
print "Элемент $ind существует\n" if exists @array[$ind];
delete($array[7]);
# Печать будет выполнена, элемент не инициализирован
print "Элемент $ind существует\n" if exists @array[$ind];
print $#array, "\n"; #Напечатает 9, хотя один элемент
#и удален функцией delete( )
Во многих практических задачах возникает необходимость обработки элементов массива скаляров
в обратном порядке, начиная с конца. Можно, конечно, осуществить это с помощью цикла for, в
котором переменная индекса уменьшается от максимального значения до минимального, позволяя,
таким образом, обработать элементы массива в обратном порядке. Однако ввиду важности задачи
обращения массива в Perl существует специальная стандартная функция
reverse( ),
эффективно
выполняющая задачу обращения массива скаляров. Ее единственным параметром являются массив
скаляров, а возвращаемым значением – список значений элементов массива в обратном порядке:
@array = (10, 20, 30, 40);
@reverse = reverse(@array); # @reverse =(40,30,20,10)
Задачу сортировки значений элементов массива скаляров можно быстро решить с помощью
функции
sort( ),
передав ей в качестве параметра массив скаляров. Эта функция возвратит
отсортированный в лексикографическом порядке список значений массива:
@array = (k, d, c, a);
@sort = sort(@array);
@sort = (a, c, d, k)
Если необходимо отсортировать список в другом порядке, отличном от лексикографического,
то следует в списке параметров функции sort( ) перед именем сортируемого массива через пробел
(не запятую!) указать имя подпрограммы, определяющей требуемый порядок сортировки, или в фигурных
скобках задать оператор сортировки, используя переменную $a для первого значения. Подпрограмма
или встроенный оператор сортировки должны возвращать 1, если первое значение больше второго, 0
в случае их равенства и –1, если первое значение меньше второго. Обычно для этих целей
используются операции числового <=> и строкового cmp сравнения, которые представлены в главе 4:
# Сортировка в обратном порядке
@sort = sort({$b cmp $a} @array); # @sort = (k, d, c, a)