Программирование на perl — доступ и печать
for $what (keys %new_folks) # Проходим по ключам
# нового хеша
{
$HoH{flins}{$what}=$new_folks{$what};
# Заносим значение из нового хеша в старый хеш с
# ключом "flins".
}
3. Доступ и печать
А. Один элемент
print "$HoH{flins}{pal}" #->"barn"
$HoH{jetsons}{‘his boy’}=~s/(w)/u$1/;
Получаем:
Elroy вместо elroy.
Б. Печать всего хеша.
Способ 1. Временные переменные
while (($family,$roles)=each %HoH)
{print "$family: ";
while (($role,$person)=each %{$roles})
# Список ($family,$roles) пробегает пары по внешнему хешу,
# то-есть ключ $family будет принимать значения flins,
# simps, jetsons, а переменная $roles будет принимать значение
# указателя на внутренний хеш. Почему эта переменная будет
# указателем? Это все потому, что она является скалярной
# величиной, а принимает значение, которое является внутренним
# хешем.
{ print "$role=$person";
}
print "n";
}
Будет выведено:
flins: pal=barn
lead=fred
simps: kid=bart
lead=bob
wife=marge
и так далее.
Здесь приведен один из возможных вариантов. Вывод хешей будет происходить в неизвестном для нас порядке, то-есть не так, как они были сформированы.
Способ 2.
foreach $family (keys %HoH) # $family пробегает по
# ключам внешнего
# хеша
{ print "$family: ";
foreach $role (keys %{$HoH{$family}})
# $role пробегает по ключам внутреннего хеша, причем лоступ
# к внктреннему хешу идет через разыменование элемента
# $HoH{$family}, который является указателем на внутренний хеш.
{
print "$role=$HoH{$family}{$role}";
# Здесь доступ к элементу происходит через две скобки, как
# к двумерному массиву, только для хешей.
}
print "n";
}
Результат вывода будет аналогичен.
В. Печать с элементами сортировки.
Способ 1. Сортировка по ключам
foreach $family (sort keys %HoH)
# $family пробегает по ключам внешнего хеша,
# отсортированного по алфавиту.
{ print "family: ";
foreach $role (sort leys %{HoH{$family}})
#$role пробегает по ключам внутреннего хеша, также
# отсортированного по алфавиту.
{ print "role= $HoH{$family}{$role}";
}
print "n";
}
Будет напечатано:
flins: lead=fred pal=barn
jetsons: his boy=elroy lead=george wife=jane
simps: kid=bart lead=bob wife=marge
Способ 2. По числу пар
foreach $family
(sort {keys %{$HoH{$a}}<=>keys %{$HoH{$b}}})
# Переменная $family прбегаеи по ключам внешнего хеша,
# отсортированного по количеству ключей внкьреннего хнша. Причем
# сортировка будет идти по возрастанию количества ключей.
{ # тело внешнего цикла
print "$family: ";
foreach $role (sort keys %{$HoH{$family}})
# Во внутреннем цикле сортировка происходит по алфавиту
№ ключей внутреннего хеша
{
print "$role=$HoH{$family}{$role}";
}
print "n";
}
Способ 3. Сортировка по рангу.
$i=0;
for (qw (lead wife son daughter pal pet),"his boy")
# Функция qw преобразует строку в список через запятые. Мы # к нему добавили элемент из двух слов. В качестве переменной
# цикла применена внутренняя переменная $_.
{
$rank {$_}=++$i;
# Формируем хеш, у которого знаяения – это ранг, то-есть
# число, которое задает порядок.
}
# Хеш %rank имеет значения, которые являются рангами
# каждого ключа — это числа от 1 до n.
foreach $family
(sort {keys %{$HoH{$a}}<=>keys %{$HoH{$b}}} keys % HoH)
# Как и в предыдущем примере здесь сортировка внешних
# ключей по возрастанию по количеству ключей во внутренних
# хешах.
{ print "$family: ";
#Печать внутреннего хеша по рангу ключей.
foreach $role
(sort {$rank{$a} <=>$rank{$b}} keys %{$HoH{$family}})
# Сортировка ключей внутреннего хеша по рангу, то-есть в
# том порядке, что задается в хеше %rank.
{
print "role= $HoH{$family}{$role}";
# По тем ключам, что не включены в список ранга, будет
# выводится информация о том, что элементы не определены в
# последней печати.
}
print "n";
}
V. Более сложные структуры
Ранее мы рассматривали только двууровневые структуры, где любой элемент такой — что и другие.
Сейчас рассмотрм случай, когда любой элемент может быть любым типом:
— число;
— Строка;
— ссылка на любой из всех;
— указатель на именованную и анонимную функции;
— и др.
Пример 1. Базовая структура — указатель на хеш.
Ключи будем обозначать прописными буквами.
$rec={
TEXT => $string, # строка
SEQUENCE => [@old_value], # массив
LOOKUP => {%some_table}, # хеш
THATCODE => &some_func, # указатель на
# именованную функцию
THISCODE => sub # указатель на
{$_[0]**$_[1]}, # анонимную функцию,
# где $_[0]и $_[1]–
# первые два аргумента
HANDLE => *STDOUT, # указатель на
# специальный тип –
# таблицу символов
};
Использование
print $rec->{TEXT}; # печать строки $string
print $rec->{SEQUENCE}[0]; # печать первого
# элемента массива
# @old_value
$last = pop @ { $rec ->{SEQUENCE}}; # последний элемент массива
# заносится в переменную
# $last, причем в массиве
# этот элемент удаляется
print $rec -> {LOOKUP} {"key"}; # печать значения по ключу
# "key" из хеша %some_table
($first_k, $first_v)= each % {$rec->{LOOKUP}};
# Пара $first_k и $first_v принимает первую пару хеша
# %some_table. Оператор each работает только над хешами, поэтому
# производим приведение типа к хешу.
$answer=&{$rec->{THATCODE}}($arg); # вызов именованной функции
# с аргументом $arg.
$answer=&{$rec->{THISCODE}}{$arg1,$arg2}; # вызов неименованной
# функции с
# аргументом $arg1 и
# $arg2.
Как видно, различий в вызове этих функций – нет
print {$rec->{HANDLE}} "a stringn";
или
$rec->{HANDLE}-> print("a stringn");
# вывод через стандарный вывод строки. Действия в том и
# другом случаях одинаковы.
Пример 2
В хеше каждый элемент имеет сложную структуру. Внешние ключи "flins", "jetsons" и "simps".
%TV={
flins=> {
series => "flins",
days =>[qw(Monday Thursday friday)],
members=> [
{ name=>"fred",
role=>"lead",
age =>"36"},
{ name=>"wilma",
role=>"wife",
age =>"31"},
{ name=>"bob",
role=>"kid",
age =>"4"}, ],},
jetsons=>{
series =>"jetsons",
days =>[qw(wednesday, saturday)],
members=>[
{ name=>"george",
role=>"lead",
age =>"41"},
{ name=>"jane",
role=>"wife",
age =>"39"},
{ name=>"elroy",
role=>"kid",
age =>"9"},],},
simps=>{
series =>"simps",
days =>[qw(monday)],
members=>[
{ name=>"hower",
role=>"lead",
age =>"34"},
{ name=>"marge",
role=>"wife",
age =>"35"},
{ name=>"bart",
role=>"kid",
age =>"11"},],},};
%TV – хеш 3 элемента
|
flins хеш 3 элемента
series — строка
days — массив
members – массив 3 элемента
хеш для lead
хеш для wife
хеш для kid
Для генерации достаточно файла или подпрограммы с помощью операторов do и require.
Построим куски один за другим:
$rec={}; # $rec — указатель на хеш, так как
# справа стоят фигурные скобки
$rec->{series}= "flins"; # заполняем пару по ключу series
$rec->{days}= [find_days()]; # заполняем пару по ключу days,
# причем значением является
# массив, выданный функцией
# find_days()
@members=(); # вводим пустой массив @members
Будем считать, что файл содержит пары в виде field=value.
while(<>)
{
%fields=split/[s=]+/; # считываем строки файла и
# разбиваем каждую строку на
# элементы по разделителям
# "Пробел" и знаку "=". Нечетный
# элемент будет ключом, а четный –
# значением, то-есть формируем
# промежуточный хеш %fields.
push @members,{%friends}; # заносим хеш в массив @members
# как очередной элемент массива.
}
$rec->{@members}=[@members]; # формируем пару хеша по ключу