Пятница, 24.11.2017, 10:22
Приветствую Вас Гость | RSS
Главная | Лекции | Регистрация | Вход
Меню сайта
Форма входа
Логин:
Пароль:
Категории раздела
Лекция [24]
Мини-чат
100
Поиск
Наш опрос
Оцените мой сайт
Всего ответов: 2
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0
    Программирование Perl
    Главная » Статьи » Лекция » Лекция

    Лекция 6.2: Хэши

    Функции работы с хэшами

    При обработке данных в хэше часто возникает необходимость проверить наличие в нем элемента с определенным ключом.Функция exists проверяет, содержится ли указанный ключ в хэше. Если ключ найден, она возвращает истинное значение ('1'), - и ложное значение (пустую строку), если такого ключа в хэше нет. При этом ассоциированное с ключом значение не проверяется и может быть любым, в том числе и неопределенным. Так можно проверить наличие ключа в хэше:

     
    print "ключ $key найден" if exists $hash{$key};
     

    При помощи функции defined(), возвращающей истинное или ложное значение, можно проверить, было ли задано значение в элементе хэша, ассоциированное с указанным ключом, или оно осталось неопределенным. Например:

     
    print "с ключом $key связано значение" if defined $hash{$key};
     

    Проверка с помощью функции defined($hash{$key}) отличается от проверки значения элемента на истинность значения$hash{$key}, так как значение элемента может быть определено, но равно нулю или пустой строке, что тоже воспринимается как ложь.

     

    Воспользовавшись функцией undef(), можно удалить из хэша только значение элемента, не удаляя его ключа, то есть сделать его неопределенным:

     
    undef $hash{$key }; # сделать значение неопределенным
     

    После того как значение элемента было удалено функцией undef(), проверки наличия в хэше ключа и значения указанного элемента хэша дадут следующие результаты:

     
    $hash{$key} # неопределенное значение - это ложь
    defined $hash{$key} # ложь, ибо значение не определено
    exists $hash{$key} # истина, ибо ключ есть
     

    Неопределенное значение, хранимое в элементе хэша, означает, что необходимый поисковый ключ присутствует, но с ним не ассоциировано никакого значения.

     

    Добавление элементов в хэш выполняется операцией присваивания, а удаление - функцией delete. Эта функция по указанному элементу удаляет из хэша соответствующую пару "ключ - значение" и возвращает только что удаленное значение. Это делается так:

     
    $deleted_value = delete $hash{$key}; # удалить элемент
     

    Если аргументом функции delete будет несуществующий элемент массива, то она просто вернет неопределенное значение, не вызвав ошибки при выполнении программы.

     

    При работе с элементами хэша очень удобно иметь список всех его ключей. Его возвращает функция keys. Полученный списокможно сохранить в массиве для дальнейшей обработки:

     
    @hash_keys = keys %hash; # поместить список ключей в массив
     

    Возможно также использовать список ключей для доступа в цикле ко всем значениям хэша. Так можно напечатать частотный словарь из предыдущего примера:

     
    foreach my $word (keys %hash) { # для каждого ключа хэша
     print "$word встретилось $hash{$word} раз\n";
    }
     

    Элементы хэша, как и другие скалярные величины, помещенные в обрамленную двойными кавычками строку, заменяются своими значениями. Кстати, можно переписать последний пример, добавив сортировку ключей для вывода слов в алфавитном порядке. А для организации цикла можно применить модификатор foreach, совмещающий очередной элемент списка с переменной по умолчанию $_:

     
    print "$_ встретилось $hash{$_} раз\n" 
     foreach (sort keys %hash);
     

    Следует помнить, что если размер хэша велик, то и полученный с помощью функции keys массив ключей тоже будет занимать большой объем памяти. В скалярном контексте функция keys возвращает количество ключей в хэше, поэтому с ее помощью можно легко проверить, не пустой ли хэш:

     
    if (keys %hash) { # если scalar(keys(%hash)) != 0
     # обработать элементы хэша, если он не пуст
    }
     

    Пустой хэш в скалярном контексте возвращает ложное значение (строку '0'), а непустой - истинное. Поэтому проверить, пуст ли хэш, можно еще проще - употребив имя хэша в скалярном контексте, что часто используется в конструкциях, проверяющих условие:

     
    while (%hash) { # или scalar(%hash) != 0 (не пуст ли хэш?)
     # обработать элементы хэша
    }
     

    Встроенная функция values, дополняющая функцию keys, возвращает список всех значений элементов хэша в том же порядке, в каком функция keys возвращает ключи. С полученным списком можно поступать обычным образом: например, сохранить в массиве или обработать в цикле:

     
    @hash_values = values %hash; # сохранить все значения хэша
    print "$_\n" foreach (values %hash); # вывести значения
     

    В скалярном контексте функция values возвращает количество значений в хэше, так что ее можно использовать для того, чтобы узнать размер хэша. Например:

     
    $hash_size = values %hash; # число значений в хэше
     

    Функция each является встроенным итератором - программной конструкцией, контролирующей последовательную обработку элементов какой-либо коллекции данных. Она предоставляет возможность последовательно обработать все ассоциативные пары в хэше, организуя перебор всех его элементов. При каждом вызове она возвращает двухэлементный список, состоящий из очередного ключа и значения из хэша. Пары элементов возвращаются в неизвестном заранее порядке.

     
    ($key, $value) = each %hash; # взять очередную пару элементов
     

    После того как будет возвращена последняя пара элементов хэша, функция each возвращает пустой список. После этого следующий вызов each начнет перебор элементов хэша сначала. С ее помощью удобно организовать обработку всех элементов хэша в цикле, который закончится, когда each вернет пустой список, означающий "ложь":

     
    while (my ($key, $value) = each %hash) { # пока есть пары
     # обработать очередные ключ и значение хэша
     print "с ключом $key связано значение $value\n";
    }
     

    Иногда требуется искать ключи хэша по их значениям. Для этого нужно создать обратный ассоциативный массив (или инвертированный хэш), поменяв местами значения и ключи хэша. Это можно сделать так:

     
    while (my ($key, $value) = each %hash_by_key) { # ключи хэша
     $hash_by_value{$value} = $key; # становятся значениями
    }
     

    Этого же результата можно достичь с помощью функции reverse, воспользовавшись тем, что она воспринимает хэш как список, в котором за каждым ключом идет значение, и меняет порядок всех элементов этого списка на обратный. Функция reverseвозвращает список, в котором в каждой паре элементов за значением следует ключ, и этот список присваивается новому хэшу:

     
    %hash_by_value = reverse %hash_by_key; # переворот списка
    $key = $hash_by_value{$value}; # поиск по бывшему значению
     

    Нечетные элементы инвертированного списка становятся ключами, а четные - значениями хэша %hash_by_value.

    Хэши и списки

    Так как весь хэш, его ключи или значения можно легко преобразовать в список, то для обработки хэшей можно применять любые функции, работающие со списками. Именно поэтому в предыдущем примере была применена функция reverse. Например, вывести ключи и значения хэша на печать можно так:

     
    { # организовать блок, где объявить временный массив
     my @temp = %hash; # сохранить в нем хэш 
     print "@temp"; # и передать его функции print
    } # по выходе из блока временный массив будет уничтожен
     

    Можно напечатать хэш по-другому, построчно и в более облагороженном виде, при помощи функции map, которая также выполняет роль итератора:

     
    print map {"Ключ: $_ значение: $hash{$_}\n" } keys %hash;
     

    В этом примере на основании списка ключей, возвращенного функцией keysфункция map формирует список нужных строк, вставляя из хэша в каждую из них ключ и значение. Она возвращает сформированный список функции print, которая выводит его в выходной поток. Кстати, это типичный для Perl прием - обрабатывать данные при помощи цепочки функций, когда результат работы одной функции передается на обработку другой, как это принято делать с помощью конвейеров команд в операционных системах семейства Unix.

     

    В приведенных выше примерах при необходимости обработки ключей хэша в алфавитном порядке они сортировались с помощью функции sort. Вот пример обработки хэша в порядке возрастания не его ключей, а его значений:

     
    foreach $key ( # каждый элемент списка,
     sort # отсортированный по порядку
     {$hash{$a} cmp $hash{$b}}# значений, ассоциированных
     keys %hash) { # с ключами хэша
     print "значение:$hash{$key} ключ:$key\n"; # обработать
    } # в цикле
     

    Здесь в блоке сравнения функции sort сопоставляется значения хэша, ассоциированные с очередными двумя ключами из списка, который предоставлен функцией keys.

     

    Срезы хэшей

    Подобно тому, как при работе с массивами срезы позволяют работать со списком элементов, в Perl есть возможность обращаться сразу с несколькими элементами хэша. Это делается с помощью среза хэша. Срез хэша (hash slice) - это список значений хэша, заданный перечнем соответствующих ключей. Он записывается в виде имени хэша с префиксом @ (так как срез - это список), за которым в фигурных скобках перечисляются ключиСписок ключей в срезе хэша можно задать перечислением скалярныхзначений, переменной-списком или списком, возвращенным функцией. Например, так:

     
    @hash{$key3, $key7, $key1} # срез хэша задан списком ключей
    @hash{@key_values} # срез хэша задан массивом
    @hash{keys %hash} # то же, что values(%hash)
     

    Если в срезе хэша список ключей состоит из единственного ключа, срез все равно является списком, хотя и из одного значения. Сравните:

     
    @hash{$key} # срез хэша, заданный списком из одного ключа
    $hash{$key} # значение элемента хэша, заданное ключом
     

    Поскольку переменная-хэш в составе строки не интерполируется, для вставки в строку всех значений хэша можно воспользоваться срезом хэша:

     
    %hash = ('0' => 'false', '1' => 'true');
    "@hash{keys %hash}"; # будет "false true" или "true false"
     

    Срез хэша, как и любой другой список, может стоять в левой части операции присваивания. При этом списку ключей среза должен соответствовать список присваиваемых значений в правой части присваивания. Воспользовавшись срезом, можно добавить в хэш сразу несколько пар или объединить два хэша, добавив к одному другой. Например:

     
    @hash{$k1, $k2, $k3}= ($v1, $v2, $v3); # добавить список
    @old{keys %new}= values %new; # добавить хэш %new к %old
     

    С помощью среза хэша и функций keys и values можно поменять в хэше местами ключи и значения, то есть сделать значенияключами, а ключи - значениями.

     
    @hash_keys = keys %hash; # сохранить ключи в массиве
    @hash_values = values %hash; # сохранить список значений
    %hash = (); # очистить хэш
    @hash{@hash_values}=@hash_keys; # срезу хэша присвоить список
     

    Специальные хэши

    Исполняющая система Perl предоставляет программисту доступ к специальным ассоциативным массивам, в которых хранитсяполезная служебная информация. Вот некоторые из специальных хэшей:

     
    %ENV перечень системных переменных окружения (например, PATH)
    %INC перечень внешних программ, подключаемых по require или do
    %SIG используется для установки обработчиков сигналов от процессов
     

    Например, так при выполнении программы можно использовать значения переменных окружения: перечислить все их значения или выбрать нужные.

     
    foreach my $name (keys %ENV) { print "$name=$ENV{$name}\n"; }
    ($who, $home) = @ENV{"USER", "HOME"}; # под Unix
    ($who, $home) = @ENV{"USERNAME", "HOMEPATH"}; # и Windows XP

     

    Категория: Лекция | Добавил: mazay (13.05.2014)
    Просмотров: 165 | Рейтинг: 0.0/0
    Всего комментариев: 0
    Добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]
    Создать бесплатный сайт с uCozCopyright MyCorp © 2017