Программирование на perl — доступ к массиву, заданному ссылками
Здесь через двойной указатель доступ в начале к элементам-строкам, а потом уже в строке доступ к конкретному элементу.
Если же мы будем печатать @LoL, то будут выданы указатели, например,
ARRAY(0x650c34) ARRAY (0x6557e0) ARRAY(0x655858)
А print $LoL[1] даст один указатель
ARRAY(0x6557e0)
Способ 1 (через указатель)
for $arr_ref (@LoL)
{ print "[@$arr_ref]n";
}
Вначале – указатель, потом – разыменование.
При печати будет выдано:
1я строка массива
2я строка массива
……………………………
и т. д.
Способ 2 (аналогично, только через индекс)
for $i (0..$#LoL)
{ print "[@{$LoL[$i]}]n";
}
Здесь $#LoL – размерность массива, но не двухмерного, а одномерного, то-есть $#LoL=2 для нашего случая. Переменная $i пробегает значения $i=0,1,2, а $LoL[$i] — указатель на соответствующую строку массива. Потом разименование элемента.
Данный способ предпочтительней, так как из этого способа можно перейти уже к двумерному массиву.
Доступ к каждому элементу
Способ 1
for $i (0..$#LoL) # $#LoL последний
# индекс массива
{ for $j (0..$#{$LoL[$i]}) # $#{$LoL[$i]} –
# последний индекс
# элемента в i –строке
# Фигурные скобки для
# того, чтобы разбить
# операцию $# и
# получить доступ к
#элементу массива
# $LoL[$i].
{ print "$LoL[$i][$j] "; # Печать строки
# элементов в виде
# строки
}
print "n"; # Переход для первой
# строки массива.
}
Способ 2 (через ссылки)
for $i (0..$#LoL)
{ $aref=$LoL[$i];
for $j (0.. $#{$aref})
{ print "$aref->[$j]";
}print "n";}
Здесь $aref играет рольуказателя на промежуточный массив. Так как мы не разыменвываем указатель, то обращаемся через оператор ->.
Способ 3 (аналогично способу 2)
for $i (0..$#LoL)
{ $aref=$LoL[$i];
for $j (0.. @$aref-1)
{ print "$aref->[$j]n";
}
}
Во втором способе мы применяли операцию $# для нахождения индекса последнего элемента в строке. А в данном случае – мы разыменвываем указатель $aref, а потом в скалярном контексте работает массив @$aref. Так как здесь определяется количество элементов в строке, то мы и в связи с этим вычитаем единицу.
Доступ к массиву, заданному ссылками
Пусть у нас есть $ref_to_LoL – указатель на двухмерный массив.
$n=$#{$ref_to_LoL}; # $n – индекс последней
# строки двумерного массива,
# поэтому здесь не надо
# делать разыменования
for ($i=0;$i<=$n;$i++)
{ for $j (0.. $#{$ref_to_LoL->[$i]}) # Цикл по
# строкам
# массива
{ print "$ref_to_LoL->[$i][$j]n";
# Здесь определяли индекс последнего элемента в строке, # которая задана через указатель. Печать элемента с
# индексами [i, j], причем все идет через указатели.
}
}
Внимание!Если при формировании у Вас появилась строка вида [ "aa","bb"], то-есть в начале идут пробелы, то в массив будет занесено ["","aa","bb"], то-есть будет сформирован первый элемент в виде пустой строки. А при печати этой строки массива будет выведено ["aa","bb"], то-есть при печати первых пробелов нет и поэтому отсчет может быть неверным. Поэтому в этом случае можно сбиться со счета. Аналогично, если будут встречаться пустые строки, которые будут учитываться, но не будут выводиться на экран.
Применение срезов
А. При формировании
@part=();
* $x=1;
for ($y=7;$y<13;$y++)
{ push @part $LoL[$x][$y];
}
Этот цикл можно заменить
@part=@{$LoL[1]}[7..12];
Если вместо * будет цикл по $x:
for ($x=1;$x<=8;$x++)
{…………………………}
то внутренний цикл можно сделать срезом
for ($x=1;$x<=8;$x++)
{ push @part
[@{$LoL[$x]}][7..12];
}
Внимание! При печати print срезы в двухмерном массиве не действуют
II. Хеш массивов
Хеши массивов используются тогда, когда Вам предпочтительней посмотреть каждый массив отдельной строкой, чем простот по номеру индекса. Так как внешней структурогй является хеш, то мы теряем порядок следования элементов. Поэтому для печати, чтобы отследить эаданный порядок следованиянужно принмнять функцию sort.
Особенности данной структуры состоят в следующем. Первое, что это хеш, поэтому имя переиенной должно начинаться с символа %.
Второе, элемент хеша – это ключ+значение, которые заключаются в фигурные скобки.
Третье, каждое значение – это одномереый массив, заключенный в квадратные скобки, так как это один элемент.
Четвертое, привязка к ключу идет по операции =>.
1. Структура хеша массивов
%HoL=
# ключи значения как одномерный массив
{ flins => ["fred",
"barn" ],
sons => ["bob",
"lera"],
simps => ["lena",
"lora",
"vova"]
};
1. Генерация
А. Из файла
Пусть в файле строки строятся по следующему образцу:
flins: fred barn tim
В начале идет ключ с символом двоеточия, а потом строка, которая будет считаться массивом элементов.
Способ 1.
while ($line=<>) # Чтение из стандартного
# ввода или из файла, имя
# которого задано в
# переменной @ARGV.
# $line будет
# содержать строку, введенную из файла
{ ($who,$rest)=split/:s*/,$line;
# После чего строка $line разбивается на две части с
# помощью функции split по разделителю ":" и следующими за ним
# пробелами. Все, что находится до ":" будет ключом.
@fields=split ‘ ‘, $rest;
# Оставшуюся часть мы разбиваем на элементы и делаем из
# них массив. Разбивка идет по пробелам.
$HoL{$who}= [@fields];
# По ключу заносим массив в хеш, как один элемент.
}
Способ 2.
while (<>)
{ next unless s/^(.*?):s*//;
$HoL{$1}=[split];
}
Здесь – без промежуточных переменных. Рассмотрим все по частям:
а) s/^(.*?):s*//
В начале строки имеется слово, которое заканчивается на ":", и за ними – пробелы. Это слово – запоминается и удаляется из строки.
б) Если такого не произойдет, то сработает оператор next, т. е. прервет данную итерацию => будет считана следующая строка. Выражегие "next unless Условие" читается так. Если условие не выполнено, то прервать итерацию. Такая запись применяется как один из способов модификации условий.
в) Формирует элемент хеша, где ключ — слово, которое запомнили. Оставшуюся часть строки разбиваем на элементы списка.
Б. Из данных подпрограммы. Подпрограмма возвращает список элементов.
Способ 1
for $grp ("simps","sons","flins")
# Переменная $grp принимает поочередно значения из списка.
{ @members=family ($grp);
# Массиву @members присываивается список элементов, полученных из подпрограммы family.
$HoL{$grp}=[@members];
# Формируем элемент хеша.
}
Способ 2
Этот способ короче, так как без применения вспомогательных переменных.
for $grp ("simps","sons","flins")
{ $HoL{$grp}=[family($grp)];
}
В этих двух способах ключи нам известны. Можно сделать, чтобы подпрограмма возвращала ключ и список.
В. Добавление новых элементов к существующему элементу хеша.
push @{$HoL{flins}},"wilma","betty";
В операторе push – первый аргумент обязательно массив, поэтому мы хешу с ключом flins добавляем два новых элемента. Фигурные скобки между символами @ и $, чтобы разбить на составляющие: массив и элемент хеша.
2. Доступ и печать
А. print $HoL{flins}[0]
Будет выдано "fred".
Б. $HoL{sons}[1]=~s/(w)/u$1/;
Преобразование букв в верхний регистр:
jane => Jane
В этом случае происходит изменение значения элемента хеша.
А. и Б. – для одного элемента.
В. Для всех элементов
foreach $f (keys %HoL)
{ print "$f: @{$HoL{$f}}n";
}
Переменная выбирает все ключи хеша. А потом печатается ключ и значение массива по ключу, которое будет массивом, то-есть списком, элемента зеша.
Г. Для всех с индексом
foreach $f (keys %HoL)
{ print "$f:";
foreach $i (0..$#{$HoL{$f}})
{print "$i=$i:$HoL{$f}[$i]";}
print "n";
}
Начало аналогично. Извлекаем ключ хеша и печатаем его.
Потом в цикле по переменной i, которая изменяется от 0 до индекса последнего элемента в данном значении хеша, печатаем переменную $i и элементы значения хеша.
Д. С сортировкой по количеству элементов в значении
foreach $f
(sort {@{$HoL{$b}}<=>@{$HoL{$a}}} keys %HoL)
{ print "$f: @{$HoL{$f}}";
}
Переменная $f принимает значения ключей хеша, отсортированного по убыванию (так как в начале стоит $b, а потом $a). Оператор print печатает ключ и значения хеша, то-есть всего массива по этому ключу.
Е. С сортировкой по количеству
В начале – аналогично
foreach $f
(sort {@{$HoL{$b}}<=>@{$HoL{$a}}} keys %HoL)