Объединение хэшей
Проблема
Требуется создать новый хэш, содержащий элементы двух существующих хэшей.
Решение
Интерпретируйте хэши как списки и объедините их так, как это делается со списками:
%merged = (%A, %B);
Для экономии памяти можно организовать перебор элементов и построить новый хэш следующим образом:
%merged = ();
while ( ($k, $v) = each(%A) ) {
$merged{$k} = $v;
}
while ( ($k, $v) = each(%B) ) {
$merged{$k} = $v;
}
Комментарий
В первом варианте используется списковая эквивалентность, о которой говорилось во введении. (%А, %В)
интерпретируется как список пар «ключ/значение». Когда он присваивается объединенному хэшу %merged,
Perl преобразует список пар снова в хэш. Рассмотрим, как эта методика реализуется на практике:
%drink_color = ( Galliano => "yellow",
"Mai Tai" => "blue" );
%ingested_colors = (%drink_color, %food_color);
Ключи обоих входных хэшей присутствуют в выходном не более одного раза. Если в хэшах найдутся
совпадающие ключи, в итоговый хэш включается тот ключ, который встретился последним.
Прямое присваивание компактно и наглядно, но при больших размерах хэшей оно приводит к
большим расходам памяти. Это связано с тем, что перед выполнением присваивания итоговому хэшу Perl
разворачивает оба хэша во временный список. Пошаговое объединение с помощью
each,
показанное ниже, избавит вас от этих затрат. Заодно вы сможете решить, как
поступать с совпадающими ключами.
С применением each первый фрагмент записывается следующим образом:
%drink_color = (Galliano => "yellow",
"Mai Tai" -> "blue" );
%substance_color = ();
while (($k, $v) = each %food_color) {
$substance_color{$k} = $v;
}
while (($k, $v) = each %drink_color) {
$substance_color{$k} = $v;
}
Обратите внимание на повторяющийся код присваивания в циклах while. Проблема решается так:
foreach $substanceref (\%food_color, \%drink_color ) {
while (($k, $v) = each %substanceref) {
$substance_color{$k) = $v;
}
}
Если в объединяемых хэшах присутствуют одинаковые ключи, можно вставить код для обработки дубликатов:
foreach $substanceref (\%food_color, \%drink_color ) {
while (($k, $v) = each %substanceref ) {
if (exists $substance_color{$k}) {
print "Warning: $k seen twice. Using the first definition. \n";
next;
}
$substance_color{$k} = $v;
}
}
В частном случае присоединения одного хэша к другому можно воспользоваться срезом для получения
более элегантной записи:
@all_colors{keys %new_colors} = values %new_colors;
Потребуется память в объеме, достаточном для хранения списков всех ключей и значений %new_colors.
Как и в первом варианте, расходы памяти при большом размере списков могут сделать эту методику неприемлемой.
См. такжеОписание функции each
Proverte kod v komentariyah gde pro list tam oshibki detskie
Оставить комментарий:
|
|