Хеши (асоціативні масиви) в perl

Хеш - асоціативний масив, тому що доступ до даних здійснюється за допомогою ключа, асоційованого зі значенням. Хеши починаються із префікса%. % Hash. Для роботи з з хеш-масивами потрібно, як і в звичайних масивах, використовувати разименовивающій префікс $. $ Hash = сіра;

Хеш можна визначити декількома способами:

Якщо використовується пропуск при визначенні елемента хеша, то цю прогалину краще поставити в одинарні лапки $ hash = сіра;

Додати елементи в хеш можна так:

Перевірка хеша на наявність елемента:

Видалити елемент з хеша можна за допомогою функції delete.

Функція delete може викликатися для зрізу хеша, що призводить до видалення всіх зазначених ключів: delete @hash; см. perlfunc (1)

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

Для перебору елементів не дуже великого хешу можна скористатися foreach:

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

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

Вміст хеша можна вивести і так:

Висновок хеша одним рядком.

можна скористатися функцією map. print map $ hash \ n "> keys% hash;

функція map дозволяє працювати з елементами в довільному порядку, в цьому випадку створюється список рядків (ключ => значення), який передається функції print. Якщо зберегти хеш в тимчасовому масиві, то він буде виведений як рядок:

також можна вивести хеш і таким чином: print "@ \ n";

в двох останніх випадках ми інтерполіруя хеш як список, що не дозволяє передбачити або керувати порядком виведення пар "ключ / значення". Дані в останніх двох випадках виводяться у вигляді списку ключів і значень, елементи якого поділяються поточним вмістом змінної $ ". Тобто не вдасться вивести кожну пару значень на новому рядку або відокремити ключі від значень будь-яким символом. Наведемо програму, яка читає файл поштової скриньки і виводить кількість повідомлень від кожного відправника, відправник визначається по рядку From (мета програми тільки проілюструвати операції з хешамі):

Запускаємо програму читання поштової скриньки: bash-2.03 $ ./1.pl / usr / home / vovka / mbox

Для перебору елементів хеша в порядку вставки, тому що keys і each виводять елементи хешу неупорядоченно, можна скористатися модулем Tie :: IxHash

Модуль Tie :: IxHash змушує функції keys. each і values ​​повертати елементи в порядку занесення їх в хеш. Якщо у Вас немає такого модуля IxHash.pm то потрібно зайти на CPAN / modules. знайти його і встановити, якщо у вас немає прав на установку бібліотек, то в першому рядку скрипта потрібно написати #! / put '/ do / perl'a -wT -I / put' / do / nugnogo / modulia. Приклад використання Tie :: IxHash:

см. тих документацію по модулю Tie :: IxHash.

в рядку push міститься версія $ tty = $ tty для багатозначного хеша. Всі імена терміналів інтерполюються в рядку print @>.

Інвертування хеша проводиться за допомогою функції reverse. в якому асоційовані значення вихідного хеша є ключами і навпаки. Скористаємося списковому еквівалентність хеш. У списковому контексті reverse іетерпретірует% hash як список і міняє місцями складові його елементів. Наприклад: маємо хеш% Glavfish = ( "seledka" => "mokraia", "skat" => "elektricheskij"). якщо його інтерпретувати як список, то отримаємо наступне ( "seledka", "mokraia", "skat", "elektricheskij"). після інвертування список виглядає так: ( "elektricheskij", "skat", "mokraia", "seledka"). інтерпретація його як хеша дає наступне: ( "elektricheskij" => "skat", "mokraia" => "seledka"). Приклад програми, яка на назву предмета видає його властивість і навпаки:

Сортування ключів за алфавітом асоційованих значень:

Сортування по довжині асоційованих значень:

Приклад з fido7.ru.perl. Злиття хешів виконується як і злиття масивів:

Щоб заощадити пам'ять, можна скористатися таким кодом:

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

Пошук ключів, відсутніх в другм хеше:

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

Якщо в якості ключа використана невизначена величина undef. то вона перетвориться в порожню рядок. undef є цілком допустимим значенням в хеше. Але при вибірці значення для ключа, відсутнього в хеше perl видасть undef. Перевірити наявність ключа можна так: exist ($ hash); визначеність асоційованого значення: defined ($ hash); істинність: if ($ hash) ;. Іноді undef потрібно зберігати в кеші, тобто ключ є, але з ним не пов'язано нічого корисного, наприклад програма, яка визначає розмір файлів з переданого списку:

Цей код дозволяє пропустити неіснуючі і нульові файли, але записані в вихідному списку.


Як можна хеш покласти в рядок? Наприклад проблема:

tnc> Дякую, товариші :-)
tnc> До цього я вже допер. Друге питання: є логи http-gw. капосний їх
tnc> полягає в тому, що на кожен запит в балці з'являється 4 рядки,
tnc> зовсім не обов'язково йдуть підряд:

Створюєш хеш і тримаєш в ньому ті рядки, які ще, грубо кажучи, не закриті, а як закриєш - жени. Звичайно, якийсь помітний шматок файлу в пам'яті буде присутній, але не повністю же. Через скільки там рядків буває четверта від першої? Якщо в середньому через пару мільярдів, то - в морг :-)

Що-небудь типу Приклад роботи з хешем і базою даних з fido7.ru.perl (cм. Відповідь): Як передати хеш в функцію? fido7.ru.perl (див. всю дискусію)

найпростіший і сокирний варіант - зробити хеш з відповідниками типу я => ya спліт рядки і замінювати елементи отриманого масиву на потрібні. щось на кшталт:

Змінні оточення, які використовують вбудовані хеші і масиви% INC. % SIG. % ENV. % FORM<>.

% INC містить імена файлів, що включаються командами do і require. Ключ ім'я файлу, значення шлях до файлу, що включається. Масив @INC містить список дірректорію, які переглядає perl для виконання команд do, require або use.

% SIG - хеш, в якому зберігаються обробники різних ситуацій, що виникають в perl. Наприклад рядок local $ SIG = sub<>; відключає попереджувальні повідомлення.

% ENV містить значення змінних середовища (оточення), заданих на момент запуску сценарію (скрипта). Ключами зазвичай бувають імена змінних середовища (але їх склад залежить від операційної системи), зміна цих значень викличе зміна оточення для процесів нащадків. програма видає:

Безпосередньо з скрипта елементи хеша% ENV можна викликати $ ENV або $ ENV. дивлячись що потрібно викликати.

% FORM містить дані, що вводяться з форми методом POST: html форма така:






Якщо ми введемо в поле name1 qwe, name2 rty, name3 asd і натиснемо send, то через STDIN передаються дані в вигляді: name1 = qwename2 = rtyname3 = asd і вміст хеша

Значення полів name * можна отримувати $ FORM. $ FORM і т.д.