Асоціативні масиви в Perl, Perl, Програмування, статті

Андрій Новиков

Асоціативні масиви в Perl є реалізацією хеш-таблиць. Асоціативні масиви, безумовно, є унікальним і надзвичайно корисною властивістю мови Perl. Вони надзвичайно зручні для зв’язку числових або текстових значень з текстовими рядками або при підрахунку кількості входжень текстових рядків (при статистичному аналізі).

У той час як звичайна змінна в Perl має префікс $, асоціативні масиви мають префікс%. Індексами (ключами) у асоціативних масивів є рядки. Числові ключі перетворяться в рядки. Ключі полягають у фігурні дужки, а не в квадратні, як це прийнято в звичайних масивах. Значеннями можуть бути будь-які скалярні дані: рядки, числа або посилання.

Асоціативний масив може бути декларовано безпосередньо як список пар ключ-значення:

%ages = ("Andy", 22,
         "Mike", 23,
         "Dr. Jones", 27,
         "Mr. Smyth", 21,
         "Katrin", "who knows");

Звернення до елементів асоціативного масиву здійснюється таким чином:

$ages{"Dave"} = 30;

Тут “Dave” є ключем, а 30 – значенням. Зверніть увагу, що звернення до значення здійснюється з префіксом $, тому що воно є скалярним.

На відміну від звичайних масивів, у асоціативних масивів порядок проходження елементів не визначений і до них не можна звернутися по числовому індексом.

Можна перебрати по черзі всі елементи асоціативного масиву за допомогою функції foreach:

foreach $person (keys %ages)
{
   print "I know the age of $person is $ages{$person}\n";
}
foreach $age (values %ages)
{
   print "Somebody is $age\n";
}

При виклику keys повертається список ключів асоціативного масиву. При виклику values ​​повертається список значень асоціативного масиву. Ці функції повертають списки в однаковому порядку, хоча він і не має нічого спільного з порядком додавання елементів в масив.

У скалярному контексті функції keys і values ​​повертають кількість пар ключ-значення, що зберігаються в асоціативному масиві:

$num_keys = scalar keys %ages;

Даний виклик також скидає ітератор, пов’язаний з асоціативним масивом. Це може стати в нагоді при передчасному виході з циклу за допомогою функції last.

Існує також функція each, що повертає двоелементний список, що складається з ключа і значення. При кожному новому виклику вона повертає нову пару:

while (($person, $age) = each(%ages))
{
   print "$person is $age\n";
}

Ця функція не дозволяє сортувати масив. Не можна додавати нові пари в масив в процесі ітерірованія.

Існує можливість знаходження ключа по його значенню. Для цього необхідно створити зворотний асоціативний масив:

%by_value = reverse %by_key;
$key = $by_value{$value};

Але цей спосіб не зовсім ефективний. Більш ефективним (але не більш швидким) є наступний спосіб:

while (($key, $value) = each %by_key) {
     $by_value{$value} = $key;
}

У будь-якому випадку треба враховувати, що якщо в масиві є співпадаючі значення, буде знайдено лише один з ключів.

Асоціативний масив може бути перетворений в списковий простим його привласненням змінній спискового масиву. Зворотне перетворення також досягається простим привласненням:

@ Info =% ages; # @ info є списковому масивом. # Він тепер має 10 елементів $ Info [5]; # Повертає значення 27 з масиву @ info % Moreages = @ info; #% moreages є асоціативним масивом. # Він тепер ідентичний% ages

Внутрішній спосіб представлення асоціативних масивів не дозволяє передбачити порядок вибірки пар ключ-значення. Щоб упорядкувати вибірку, необхідно відсортувати список ключів або значень:

@ Persons = sort keys% ages; # сортування по ключу
@persons = sort {
             $ages{$a} cmp $ages{$b} } Keys% ages; # сортування за значенням

У наступному прикладі ми спробуємо відсортувати по числовому значенню в зворотному порядку, якщо значення виявляться однаковими, то відсортуємо по довжині ключа, а якщо і вони співпадуть, проведемо сортування послідовним ASCII порівнянням ключів:

@persons = sort {
   $ages{$b} <=> $ages{$a}
     ||
   length($a) <=> length($b)
     ||
   $a cmp $b
} keys %ages;

При наявності більш складного критерію сортування порівняння доцільно винести в окрему функцію:

foreach $key (sort ByAge keys(%ages)) {
}
sub ByAge {
	$ages{$a}<=>$ages{$b};
}

Іншою особливістю асоціативних масивів є можливість існування невизначеного значення в парі ключ-значення.

Наявність ключа в асоціативному масиві можна перевірити функцією exists:

exists $ ages {'Andy'} повертає true exists $ ages {'Nick'} повертає false

Наявність певного (дійсного) значення можна перевірити функцією defined:

defined $ ages {'Andy'} повертає true

Можна видалити з масиву значення, не видаляючи ключа функцією undef:

undef $ages{'Andy'}

Тепер:

$ Ages {'Andy'} повертає false defined $ ages {'Andy'} повертає false exists $ ages {'Andy'} повертає true

Можна також видалити з масиву цілком всю пару ключ-значення функцією delete:

delete $ages{'Andy'}

У цьому випадку:

defined $ ages {'Andy'} повертає false exists $ ages {'Andy'} повертає false

На базі асоціативного масиву можна створити тривимірний асоціативний масив. Існує багато ситуацій, коли вони необхідні, але майже неможливо знайти опис їх застосування навіть англійською мовою. Заповнимо цю прогалину.

Елементи тривимірних асоціативних масивів декларуються наступним чином:

$VisitCounter{$person}{$date}=$value;

Перебір елементів тривимірного асоціативного масиву з їх сортуванням здійснюється таким чином:

foreach $person (sort keys(%VisitCounter)) {
   $DateHash=\$VisitCounter{$person};
   foreach $date (sort keys(%{$$DateHash})) {
	  $value = $VisitCounter{$person}{$date};
   }
}

Тут, як і в попередньому випадку, можна використовувати й інші способи сортування.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*