Войти
VTEM SlideshowVTEM SlideshowVTEM Slideshow


Ассоциативные массивы в 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};
   }
}

Здесь так же можно использовать и иные способы сортировки.


Hosting tools

Who's Online

Сейчас 16 гостей и ни одного зарегистрированного пользователя на сайте