Анимация
JavaScript
|
Главная Библионтека 5.6. Перебор элементов хэша в порядке вставки 161 список строк (например, КЛЮЧ=>ЗНАЧЕНИЕ , как в приведенном выше примере), передаваемый print Два последних приема представляют собой фокусы, связанные с интерполяцией. Интерпретация хэша как списка не позволяет предсказать или управлять порядком вывода пар «ключ/значение». Более того, данные в этом случае выводятся в виде списка ключей и значений, элементы которого разделяются текущим содержимым переменной $ В отличие от других приемов, вам не удастся вывести каждую пару на новой строке или отделить ключи от значений символом =>. [> Смотри также- Описание переменной $ ь perlvar{\)\ описание функций foreach, map, keys, sort и each в perlfunc(l). Строковая иитериоляция рассматривается в рецепте 1.10, а перебор хэша - в рецепте 5.4 5.6. Перебор элементов хэша в порядке вставки Проблема Функции keys и each извлекают элементы хэша в довольно странном порядке. Вы хотите получить элементы в порядке вставки. Решение Воспользуйтесь модулем Tie::IxHash use Tie IxHash, tie %ХЭШ Tie IxHash , # Операции с хэшем %X31U ©keys = keys %X31D # Массив ©keys отсортирован в порядке вставки Комментарий Модуль Tie::IxHash заставляет функции keys, each и values возвращать элементы в порядке занесения в хэш. Это часто избавляет от необходимости заранее обрабатывать ключи хэша какой-нибудь сложной сортировкой или поддерживать отдельный массив, содержащий ключи в порядке их вставки. Tie- IxHash также представляет объектно-ориентированный интерфейс к функциям splice, push, pop, shift, unshift, keys, values и delete, a также многим другим. Следующий пример демонстрирует использование keys и each: # Инициализировать use Tie IxHash, tie %food color, Tie IxHas , $food color{Banana} = Yellow , $food color{Apple} = Green $food color{Lemon} = Yellow print "In insertion order, the foods агеДп"; foreach $food (keys %food color) { print $food\n"; print "Still in insertion order, the foods colors are:\n"; while (( Stood, Scolor ) = each %food color ) { print Sfood is colored Scolor.\n", In Insertion order, the foods are: Banana Apple Lemon Still in insertion order, the foods colors are: Banana is colored Yellow. Apple is colored Green. Lemon is colored Yellow. I> Смотри также- Документация по модулю Tie::IxHash от CPAN; рецепт 13.15. 5.7. Хэши с несколькими ассоциированными значениями Проблема Требуется хранить в хэше несколько значений, ассоциированных с одним хшючом. Решение Сохраните в хэше ссылку на массив для хранения ассоциированных значений. Комментарий в хэше могут храниться только скалярные величины. Однако ссылки являются скалярными величинами. Таким образом, проблема решается сохранением в $ХЭ111 {$КЛЮЧ} ссылки на массив со значениями, ассоциированными с ключом $КЛЮЧ. Обычные операции с хэшами - вставка, удаление, перебор и проверка сушествования - переписываются для операций с массивами (push, splice и foreach). Следующий фрагмент реализует простую вставку в хэш. Он обрабатывает выходные данные команды who(i) на компьютере с UNIX и выводит краткий список пользователей с терминалами, на которых они зарегистрированы: %ttys = 0; open(WHO, "who") or die "cant open who: S!; while (<WHO>) { (Suser, Stty) = split, push( @{Sttys{Suser}}, Stty ), 5.7. Хэши с несколькими ассоциированными значениями 163 foreach $user (sort keys %ttys) { print "$user- @t$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}}) { (sstat = stat(7dev/$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, Svalue) = @ , my $i; return unless ref( $hash->{$key} ); for ($1 = 0, $1 < (S){ $hash->{$key} }; $i++) { If ($hash->{$key}->[$i] eq $value) { splice( (S){$hash->{$key}}, $i, 1), last, delete $hash->{$key} unless (S){$hash->{$key}}, Альтернативная реализация многозначных хэшей приведена в главе 13 «Классы, объекты и связи», где они реализуются как связанные обычные хэши. > Смотри также- Описание функций splice, delete, push, foreach и exists bperlfunc{\)\ рецепт 11.1. Связи рассматриваются в рецепте 13.15. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 [ 48 ] 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |