Хэши с несколькими ассоциированными значениями

Проблема

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

Решение

Сохраните в хэше ссылку на массив для хранения ассоциированных значений.

Комментарий

В хэше могут храниться только скалярные величины. Однако ссылки являются скалярными величинами. Таким образом, проблема решается сохранением в $ХЭШ{$КЛЮЧ} ссылки на массив со значениями, ассоциированными с ключом $КЛЮЧ. Обычные операции с хэшами — вставка, удаление, перебор и проверка существования — переписываются для операций с массивами (push, splice и foreach).
Следующий фрагмент реализует простую вставку в хэш. Он обрабатывает выходные данные команды who(1) на компьютере с UNIX и выводит краткий список пользователей с терминалами, на которых они зарегистрированы:
%ttys =();
open(WHO, "who|") or die "can't open who: $!";
while (<WHO>) {
  ($user, $tty) = split;
  push( @{$ttys{$user}}, $tty );
}
foreach $user (sort keys %ttys) {
print "$user: @{$ttys{$user) }\n";
}
Вся суть этого фрагмента заключена в строке push, где содержится версия $tty {$user} = $tty для многозначного хэша. Все имена терминалов интерполируются в строке print конструкцией @{$ttys{ user}}. Если бы, например, нам потребовалось вывести владельца каждого терминала, мы бы организовали перебор анонимного массива:
foreach $user (sort keys %ttys) {
  print "$user: ", scalar( @{$ttys{$user}} ),"ttys.\n";
  foreach $tty (sort @{$ttys{$user}}) {
    @stat = stat("/dev/$tty");
    $user = @stat ? ( getpwuid($stat[4]) )[0] : "(not available)";
    print "\t$tty (owned by $user)\n";
  }
}
Функция exists может иметь два значения: «Существует ли в хэше хотя бы одно значение для данного ключа?» и «Существует ли данное значение для данного ключа?» Чтобы реализовать вторую интерпретацию, придется просмотреть массив в поисках нужной величины. Первая трактовка exists косвенно связана с функцией delete: если мы можем гарантировать, что ни один анонимный массив никогда не остается пустым, можно воспользоваться встроенной функцией exists. Чтобы убедиться, что анонимные массивы не остаются пустыми, их следует проверять после удаления элемента:
sub multihash_delete {
  my {$hash, $key, $value) = @_;
  my $i;
  return unless ref( $hash->{$key} );
  for ($i =0; $i < @{ $hash->{$key} }; $i++) {
    if ($hash->{$key}->[$i] eq $value) {
      splice( @{$hash->{$key}}, $i, 1);
      last;
    }
  }
  delete $hash->{$key) unless @{$hash->{$key} }
}

См. также

Описание функций splice, delete, push, и exists



2013-09-10 17:05:19

Proverte kod v komentariyah gde pro list tam oshibki detskie




Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: