Программирование на perl — массив хешей
{ print "$f:", join (", ", sort @{$HoL{$f}}),"n";
}
Элементы значения хеша сортируются по коду ASCII, затем склеиваются в массив с разделителем "Пробел".
III. Массив хешей
Массив хешей биспользуется тогда, когда имеется связка записей, но каждая запись в себе содержит пары ключ/значение. Эти массивы стремятся использовать более редко, чем другие однородные структуры данных.
1. Структура
Идея структуры:
Так как в начале идет массив, то-есть список, то первыми идут круглые скобки. Каждый элемент массива должен находиться в квадратных скобках. Причем в нашем случае элемент массива – это хеш, который состоит из несколькихи пар. Ккаждая пара — этоключ/значение. Причем в литерале, то-есть константе указание ключа на значение протсходит через символ =>.
@LoH= (
[lead => "fred",
friend => "barney"
],
[lead => "george",
wife => "jane",
son => "bob"
],
[lead => "vlad",
wife => "marge",
son => "tim"
]
);
2. Генерация
А. Из файла
Любая строка файла должна біть в виде:
ключ1=значение1 ключ2=значение2 …
Способ 1
while (<>) # $_ эта переменная, которая
# содержит строку файла из
# нескольких пар ключ/значение
{ $rec=(); # $rec – это указатель
for $field (split) # $field содержит очередную
# пару
{ ($key,$value)= split /=/,$field;
# Каждая пара с помощью разделителя "=" записывается в список ($ключ, $значение)
$rec->{$key}=$value;
}
push @LoH, $rec;
}
Здесь вместо указателя $rec можно применить вспомогательный хеш %vsp, что рассматривается в способе 2.
Способ 2.
Вместо $rec(указателя) используется %vspomog (вспомогательный хеш).
while (<>)
{ %vspomog={};
for $field (split)
{ ($key,$value)=split /=/,$field;
$vspomog{$key}=$value;
}
push @LoH, %vspomog;
}
Способ 3.
while (<>)
{ push @LoH, {split /[s=]+/};
}
Строка файла разбивается на список, где разделителем является пробнльные символы и знак "=", причем они могут быть один или несколько раз.
Вся строка файла будет одним элементом массива LoH. Но этот один элемент – это один хеш из нескольких пар.
Внимание! Для хеша надо фигурные скобки для массива LoH.
Б. С помощью функции. Она должна возвращать массив "ключ, значение", типа:
"lead","fred","son","bob"
Способ 1.
while (%f=pairset)
{ push @LoH,{%f};
}
Функция pairset () выдает список, в котором элементы на нечетных местах – это ключи, а элементы на четных местах – это значения. Весь этот список становится хешем %f.
Потом этот хеш заносится в массив @LoH. Для обозначения того, что это будет массив хешей, элемент массива заключен в фигурные скобки.
Способ 2.
Без временных переменных
while (<>)
{ push @LoH, {parss($_)};
}
В. Добавление пар к элементам
$LoH[0]{pet}="dino";
[0] — индекс первого элемента массива
{pet} – новый ключ
"dino" – новое значение (может быть несколько слов)
Например
$LoH[1]{pet}="santa’s little helper";
3. Доступ и печать
Способ 1. Доступ к конкретной паре:
Для этого необходимо указать следующие вещи:
— индекс массива;
— ключ пары.
print $LoH[0]{lead}
или
$LoH[1]{wife}=~s/(w)/u$1/;
Здесь мы заменили jane на Jane.
Способ 2. Доступ ко всему массиву с помощью ссылок.
for $href (@LoH) # Очередной элемент массива, то-
# есть хеш, присваивается
# переменной $href через
# указатель.
{ print "{"; # Вывод левой фигурной скобки
for $r (keys %$href)
# %$href – разыменование указателя на хеш, взять ключи этого
# хеша, поочередно проходит по списку ключей
{ print "$r=$href-> {$r}"; # Печать ключа и
# значения. Здесь
# опять указатель на
# хеш. Поэтому мы
# применили оператор # –>.
}
print "}n"; # вывод правой фигурной скобки и
# переход на новую строку
}
Любой хеш (то-есть элемент массива) будет выведен в виде:
{lead=fred sun=bob…}
Способ 3. Печать всего массива хешей с помощью индексов.
for $i (0..$#LoH) # $#LoH – индкс последнего
# элемента массива, то-есть
# последнего хеша.
{ print "$i is {";
for $r (keys (%{$LoH[$i]})) # Проход по ключам
# хеша.
# $LoH[$i] – это
# указатель на хеш с
# номером $i.
# %{$LoH[$i]} –
# разыменование
# указателя на хеш
{ print "$r= $LoH[$i]{$r}"; # Печать конкретного
# элемента хеша по
# ключу конкретного
# хеша.
}
print "}n";
}
Печать будет представлена в виде:
0 is {lead=fred sun=bob} и так далее.
IV. Хеш хешей
— наиболее гибкая из однородніх структур;
— близко к типу: запись в записи;
— каждый уровень в свои скобки;
— если ключ содержит пробелы, то он должен быть в двойных кавычках;
— для вывода в определенном порядке надо применять сортировку по ключу или значению.
1. Структура
Здесь два уровня:
В начале три ключа: flins, jetsons и simps.
Каждое значение – это в свою очередь тоже хеш. Количество пар у них может быть произвольным.
%HoH ={
flins => {
lead => "fred",
pal => "barn"
},
jetsons => {
lead => "george",
wife => "jane",
"his boy" => "elroy"; # Здесь ключ заключен
# в кавычки, так как
# он состоит из
# нескольких слов.
},
simps => {
lead => "bob",
wife => "kid",
kid => "bart"
}
};
После последних элементов во внутреннем хеше может быть поставлены запятые. Также запятая может быть поставлена после последнего хеша.
2. Генерация
А. Из файла
Любая строка файла имеет вид типа:
flins: lead=fred pal=barn pet=dino
(pal — приятель, pet — любимец)
Способ 1. С указателем
while (<>)
{
next unless s/^(.*?):s*//;
# Замена первого слова с символом ":" и пробелами за ним на # пустую строку. Само слово запоминается в $1. Если не нашли, то # прервать текущую итерацию.
$who=$1;
$rec={}; # $rec – указатель на хеш, который
# вначале пустой.
$HoH{$who}=$rec; # Хешу HoH с ключом $who
# присваиваем этот указатель на
# пустой хеш, так как внутренний
# хеш пока пустой). Поэтоиу теперь
# на элемент хеша с ключом $who
# можно ссылаться с помощью $rec.
for $f (split)
{ ($key,$value)=split /=/, $f;
# В цикле оставшуюся часть строки, что находится в
# переменной $_, разбиваем по пробелам, то-есть получаем пары
# ключ/значение. Потом эту пару разбиваем на список из двух
# элементов и присваиваем этот список переменным $key и $value.
$rec->{$key}=$value;
# Присваиваем внутреннему хешу с ключом $key значение
# переменной $value. Причем ссылка на внешний элемент хеша идет
# через указатель $rec.
}
}
Способ 2. Без указателя
while (<>)
{ next unless s/^(.*?):s//;
$who=$1;
for $f (split)
{ ($key,$value)=split /=/, $f;
$HoH{$who}{$key}=$value;
# Здесь доступ к элементу внутреннего хеша идет, как в
# двумерном массиве, только не через индексы, а через ключи.
# Этот способ более прост и боле нагляден.
}}
Б. С помощью функции.
Способ 1. Возвращает внутренние хеши в виде строки пар.
for $gr ("simps","flins","jetsons")
{ $HoH{$gr}= {family($gr)};
}
Способ 2. С помощью вызова функции, возвращающей внешний хеш, включая ссылки на созданные внутренние хеши.
sub hash_families
# Необходимо вспомнить, что при написании подпрограммы
# аргументы явно не указываются.
{ my @ref; # Объявляем локальную переиенную
# массива
foreach $gr (@_) # Цикл по аргументам, так как @_
# содержит аргументы подпрограммы,
# что будут при ее вызове.
{ push @ref, $gr, {family($gr)};
# В массив @ref заносится ключ внешнего хеша, а потом
# внутренний хеш, что дает подпрограмма family().
}
@ref; # Подпрогоамма возвращает массив @ref
}
%HoH=hash_families ("simps","flins","jetsons");
# Хешу %HoH присваивается массив, где на нечетных местах
# находятся внешние ключи, а на четных местах – внутренние хеши.
# Весь список ("simps","flins","jetsons")
# уходят в переменную @_.
В. Добавление новых элементов
Создаем новый хеш
%new_folks= # new_folks – новая родня
{ wife => "wilma";
pet => "dino";
};
Добавим это в хеш с ключом "flins".