Вивчаємо perl (lama book)

Хеш * схожий на масив, який ми розглядали вище, тим, що являє собою набір скалярних даних, окремі елементи якого вибираються по індексному значенням. На відміну від масиву, індексні значення хешу - не малі невід'ємні цілі, а довільні скаляри. Ці скаляри (звані ключами) використовуються для вибірки значень з масиву.

Елементи хешу не варті в якомусь конкретному порядку. Можете розглядати їх як стопку бібліографічних карток. Верхня половина кожної картки - це ключ, а нижня - значення. Кожен раз, коли ви ставите в хеш значення, створюється нова картка. Коли потрібно змінити значення, ви вказуєте ключ, і Perl знаходить необхідну картку. Тому порядок карток, по суті справи, ролі не грає. Perl зберігає всі картки (тобто пари ключ-значення) в особливому внутрішньому порядку, який полегшує пошук конкретної картки, тому при пошуку не доводиться переглядати всі пари. Порядок зберігання карток змінювати не можна, так що навіть і не намагайтеся **.

Ім'я хеш-змінної складається з знака відсотка (%) і букви, за якою можуть йти інші літери, цифри і знаки підкреслення числом від нуля і більше. Іншими словами, частина імені після знака відсотка схожа на

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

** Модулі типу IxHash і DB_fiIe забезпечують певний рівень упорядкування, але ціною істотного зниження продуктивності.

відповідну частину імен скалярних змінних і масивів. Крім того, точно так само, як немає ніякого зв'язку між $ fred і @fred, хеш-змінна% fred не має нічого спільного з названими об'єктами.

Найчастіше хеш створюється і використовується шляхом звернення до її елементів, а не до всього хешу. Кожен елемент хешу - окрема скалярна змінна, доступна через індекс, що представляє собою строкове значення, якого ще називають ключем. Так, звернення до елементів хешу% fred проводиться шляхом вказівки $ fred<$ключ> , де $ ключ - будь скалярний вираз. Знову підкреслимо, що звернення до елементу хешу вимагає іншого синтаксису, ніж звернення до всього хешу цілком.

Як і у випадку з масивами, нові елементи хешу створюються шляхом надання значення:

$ Fred == "bbb"; # Створює ключ "ааа", значення "bbb" $ fred (234.5> = 456.7; # створює ключ "234. 5", значення 456.7

За допомогою цих операторів в хеше створюються два елементи. При наступному зверненні до елементів (по зазначеним ключам) повертаються раніше записані значення:

print $ fred ( "ааа"); # Виводить на екран "bbb" $ fred

При зверненні до неіснуючого елементу повертається значення undef (як і при зверненні до відсутнього елемента масиву або до невизначеної скалярної змінної).

Литеральное уявлення хешу

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

@fred_list =% fred; # @fred_list отримує значення

# ( "Ааа", "bbb", "234.5", "456.7")% barney = @fred_list; # Створити% barney як% fred% barney =% fred; # Прискорений метод виконання цього завдання% smooth "(" ааа "," bbb "," 234.5 "," 456.7 ");

# Створити% smooth як% fred з літеральних значень

Порядок пар ключ-значення в цьому розгорнутому форматі довільний і контролю не піддається. Навіть якщо ви міняєте місцями якісь значення або створюєте хеш цілком, що повертається розгорнутий список все одно буде стояти в тому порядку, який Perl вибрав для забезпечення ефективного доступу до окремих елементів. На жодну конкретну послідовність розраховувати не можна.

% Сміттю =% original; # Копіювати з% original в% сміттю

Використовуючи операцію reverse, можна створити хеш, в якому ключі і значення поміняються місцями:

% Backwards = reverse% normal;

Звичайно, якщо% normal має два ідентичних значення, то в% backwards вони перетворяться в один елемент, тому дану операцію найкраще виконувати тільки над хешамі з унікальними ключами і значеннями.

У цьому розділі перераховані деякі функції, призначені для обробки хешів.

Функція keys (% імя_хеша) видає список всіх поточних ключів, наявних в хеше% імя_хеша. Іншими словами, застосування цієї функції еквівалентно поверненню всіх елементів списку з непарними номерами (перший, третій, п'ятий і т.д.) шляхом розгортання хешу% імя_хеша в обліковому контексті, причому функція keys повертає їх саме в цьому порядку. Якщо елементи в хеше відсутні, функція keys повертає порожній список.

Застосуємо цю функцію до хешу з попередніх прикладів:

Olist = keys (% fred); # @list отримує значення ( "ааа", 234.5) # або (234.5, "ааа")

Як і у всіх інших вбудованих функціях, круглі дужки не обов'язкові: функція keys% fred повністю ідентична keys (% fred).

foreach $ key (keys (% fred)) (# одноразово для кожного значення хешу% fred

print "at $ key we have $ fred ($ key> \ n"; # показати ключ і значення>

Цей приклад демонструє також, що окремі елементи хешу можуть інтерполювати в рядки в подвійних лапках. Весь хеш, однак, інтерполювати таким чином не можна *.

У скалярному контексті функція keys видає число елементів (пар ключ-значення), що містяться в хеше. Наприклад, ви можете з'ясувати, порожній чи хеш, так:

if (keys (% xeni)) <# если keys() не равно 0:

; # Масив не порожній)

while (keys (% xem) <10)

; # Продовжувати цикл, поки менше 10 елементів>

Для того щоб дізнатися, порожній хеш чи ні, потрібно просто використовувати функцію% хеш в скалярному контексті:

if (% хеш) (# якщо "істина", в ньому щось є

Функція values ​​(% імя_массіва) повертає список всіх поточних значень зазначеного масиву в тому ж порядку, в якому функція keys (% імя_массіва> повертає ключі. Як завжди, круглі дужки не обов'язкові. Наприклад:

% Lastname = 0; # Зробити% lastname порожнім $ lastname ( "fred"> = "flintstone";

Olastnames = values ​​(tiastname); # Отримати значення

Масив @lastnames буде містити або значення ( "flintstone", "rubble"), або ( "rubble", "flintstone").

Для виконання циклу над усім хешем (тобто для перевірки кожного його елемента) можна використовувати функцію keys і отримувати значення по повертається нею ключам. Дійсно, цей метод широко використовується, але є і більш ефективний спосіб - функція each (% імя_хеша), яка повертає пару ключ-значення як двоелементний список. При кожному обчисленні цієї функції для одного хешу повертається чергова пара ключ-значення, поки не будуть перевірені всі елементи. Якщо пар більше немає, each повертає порожній список.

* Можна, в принципі, за допомогою зрізу, але тут про зрізах ми не говоримо.

Наприклад, щоб пройти по хешу% lastname з попереднього прикладу, потрібно використовувати щось таке:

while (($ first, $ last) = each (% lastname))

print "The last name of $ first is $ last \ n";

Присвоєння нового значення всьому хешу змушує функцію each перейти в його початок. Додавання елементів в хеш і видалення з нього елементів в ході виконання циклу цілком може "заплутати" функцію each (і вас, напевно, теж).

% Fred = ( "aaa", "bbb", 234.5,34.56); # Додати в% fred два елементи delete $ fred ( "aaa">; # тепер в хеше% fred тільки одна пара ключ-значення

Як і в випадку зі змінною-масивом (або обліковим літералом), можна скористатися зрізом хешу, що дасть можливість звертатися не до одного його елементу, а одночасно до набору елементів. Візьмемо, наприклад, результати гри в кеглі:

Все це можна записати одним рядком:

Але навіть вона занадто довга, тому давайте використаємо зріз хешу:

Ось так набагато коротше. Можна поєднувати використання зрізу хешу і інтерполяції змінних:

@players = qwffred barney dino);

print "scores are: @score (@players> \ n";

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

Тут значення хешу% score зливаються з хешем% league. Це еквівалентно виконанню набагато більш повільної операції:

% League = (% league,% score); = # Злити% score з% league

1. Напишіть програму, яка читає рядок, а потім виводить цей рядок і відповідне їй значення відповідно до наведеної нижче таблиці:

2. Напишіть програму, яка читає ряд слів (по одному в рядку) до кінця файлу, а потім виводить на екран зведення про те, скільки разів зустрілося кожне слово. (Додаткове завдання: відсортуйте з'являються на екрані слова по їх ASCII-значень в порядку зростання останніх.)

Схожі статті