ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
5.10. Merging HashesProblemYou need to make a new hash with the entries of two existing hashes. SolutionTreat them as lists, and join them as you would lists. %merged = (%A, %B); To save memory, loop over the hashes' elements and build a new hash that way: %merged = (); while ( ($k,$v) = each(%A) ) { $merged{$k} = $v; } while ( ($k,$v) = each(%B) ) { $merged{$k} = $v; } DiscussionThe first method, like the earlier recipe on inverting a hash, uses the hash-list equivalence explained in the introduction. Here's an example of that technique: # %food_color as per the introduction %drink_color = ( Galliano => "yellow", "Mai Tai" => "blue" ); %ingested_color = (%drink_color, %food_color); Keys in both input hashes appear only once in the output hash. If a food and a drink shared the same name, for instance, then the last one seen by the first merging technique would be the one that showed up in the resultant hash. This style of direct assignment, as in the first example, is easier to read and write, but requires a lot of memory if the hashes are large. That's because Perl has to unroll both hashes into a temporary list before the assignment to the merged hash is done. Step-by-step merging using The first example could be rewritten to use the # %food_color per the introduction, then %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; } That technique duplicated the foreach $substanceref ( \%food_color, \%drink_color ) { while (($k, $v) = each %$substanceref) { $substance_color{$k} = $v; } } If we were merging hashes with duplicates, we can insert our own code to decide what to do with those duplicates: 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; } } In the special case of appending one hash to another, we can use the hash slice notation to give an elegant shorthand: @all_colors{keys %new_colors} = values %new_colors; This requires enough memory for lists of the keys and values of See AlsoThis is a variation on Recipe 4.9; the |