`

Михаил Шохирев - Язык программирования Perl

1 ... 12 13 14 15 16 ... 55 ВПЕРЕД
Перейти на страницу:

Можно то же самое записать еще более кратко с помощью модификатора foreach, который поочередно перебирает все элементы массива, рассматривая специальную переменную $_ как синоним текущего элемента массива (то есть переменная $_ совмещается с очередным элементом массива):

print "$_ " foreach @array;

Так что каждый Perl-программист выбирает свой способ перебора всех элементов массива в полном соответствии с лозунгом TIMTOWTDI.

Обратите внимание, что значения элементов массива, будучи обычными скалярами, интерполируются в строках, заключенных в двойные кавычки. Целые массивы тоже интерполируются, если имя массива появляется в строке, обрамленной двойными кавычками. При этом значения элементов массива разделяются символом, хранящимся в специальной переменной $" (по умолчанию - пробелом). Вот еще один способ напечатать значения всех элементов массива, разделяя их двоеточиями:

$" = ':'; # установим разделитель элементов print "@array";

С помощью индексов можно обращаться не только к элементам массива, но и к элементам списка, в том числе и литерального. Для этого после закрывающей скобки списка указывается значение индекса в квадратных скобках:

$fifth = (10..15)[5]; # то же, что $fifth = 15;

Обращение по индексу к элементу в списке констант приобретает смысл, если индекс динамически вычисляется при выполнении программы. Вот, например, один из способов преобразовать десятичное число в шестнадцатеричное:

$hex = (0..9,'A'..'F')[$dec]; # при $dec==12 в $hex будет 'C'

Подобным же образом удобно обращаться к элементу списка, возвращаемого функцией. Например, так можно извлечь день месяца, зная, что у него 3-й индекс в результирующем списке функции localtime:

$month_day = (localtime)[3]; # элемент списка с индексом 3

В Perl есть удобная форма обращения к нескольким элементам массива одновременно, называемая срезом массива. Срез (slice) - это набор элементов массива, заданный списком индексов этих элементов. Срез обозначается квадратными скобками после имени массива, в которых перечислены индексы элементов. Поскольку значение среза - это список, при записи среза перед именем массива сохраняется префикс @. Срез массива в частном случае может состоять из одного значения, заданного одним индексом. Вот примеры срезов массивов:

@array[0,1] # то же, что ($array[0], $array[1]) @array[5..7] # то же, что ($array[5],$array[6],$array[7]) @array[3,7,1] # то же, что ($array[3],$array[7],$array[1]) @array[@indexes] # срез, заданный массивом индексов @array[5] # список ($array[5]), а не скаляр $array[5]

С помощью срезов удобно одновременно манипулировать значениями нескольких элементов, находящихся в любом месте массива:

# присвоить значения пяти элементам: @array[5..9] = qw(FreeBSD Linux MacOS NetWare Windows); # поменять местами значения 1-го и последнего элементов: @array[0,-1] = @array[-1,0]; # напечатать элементы с индексами от $start до $finish print @array[$start .. $finish];

Срезы могут применяться не только к массивам, но и к любым спискам, в том числе литеральным.

Для работы с таким популярным типом данных, как массивы, в Perl существует много удобных функций. Когда требуется организовать обработку списка, поочередно извлекая из него элементы, начиная с первого, применяется встроенная функция shift. Она удаляет из массива первый элемент, возвращая его значение. Когда shift применяется к пустому списку, она возвращает неопределенное значение:

$first = shift @array; # извлечь первый элемент в $first # синоним: ($first, @array) = @array;

С помощью этой функции можно организовать цикл обработки массива, который закончится после извлечения из него последнего элемента, например:

while (my $first = shift @array) { # пока @array не опустеет print "Обработан элемент $first."; print "Осталось ", scalar @array, " элементовn"; }

Обратите внимание, что для вывода текущего размера массива нужно использовать scalar @array потому, что иначе print воспримет @array как список для печати и выведет значения массива. Существует противоположная shift функция unshift, которая вставляет свои аргументы в массив перед первым элементом, сдвигая существующие элементы вправо.

unshift @array, $e1,$e2,$e3; # вставить значения в начало # синоним: @array = ($e1,$e2,$e3, @array);

С помощью массива можно организовать стек, данные в котором обрабатываются по алгоритму LIFO ("last in, first out", "последним пришел - первым ушел"). Для добавления данных в стек применяется операция push, которая добавляет элементы в конец массива:

push @stack, $new; # добавить элемент в конец массива # синоним: @stack = (@stack, $new);

Для извлечения одного значения из стека служит встроенная функция pop, которая удаляет последний элемент массива, возвращая его значение:

$last = pop @stack; # изъять последний элемент массива

При помощи комбинации функций push и shift можно организовать список, реализующий очередь данных, у которой элементы добавляются в конец, а извлекаются из начала (в соответствии с алгоритмом FIFO, "first in, first out", "первым пришел - первым ушел").

Для удаления или замены подсписка в массиве можно использовать функцию splice, которая удаляет идущие подряд элементы массива, заданные индексом первого элемента и количеством удаляемых элементов, и заменяет их новым списком (если он указан), возвращая список удаленных элементов.

@array = (1..7); # исходный массив $offset = 2; $size = 4; # смещение и размер удаляемого списка @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 "@arrayn"; # результат: А Л О К О Н Е Ц Н А Ч

Функция map позволяет выполнить действия над всеми элементами массива, поэтому ее нередко используют вместо цикла. У этой функции есть две формы вызова:

@result = map ВЫРАЖЕНИЕ, СПИСОК @result = map БЛОК СПИСОК

Она вычисляет выражение или блок для каждого элемента списка и возвращает список результатов. С ее помощью, например, можно выполнить арифметическое действие над всеми элементами списка:

1 ... 12 13 14 15 16 ... 55 ВПЕРЕД
Перейти на страницу:

Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Михаил Шохирев - Язык программирования Perl, относящееся к жанру Прочая околокомпьютерная литература. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.

Комментарии (0)