Re: Change Request for perlfaq4

[email protected] (brian d foy) Wed, 22 Nov 2006 18:29:05 -0800
Newsgroups perl.perlfaq.workers
Message-ID <221120061829054769%[email protected]>
[[ This message was both posted and mailed: see
   the "To," "Cc," and "Newsgroups" headers for details. ]]

In article <[email protected]>, Roland Minner
<[email protected]> wrote:


> I'd like to request a change in perlfaq4. It recommends the usage of each()
> to iterate over all elements of a hash.
> This isn't always true.

Yes, that answer should mention the traps with each() (just like
perlfunc does), and it should show the keys method too.

Here's the answer I replaced it with:

-------

=head2 How do I process an entire hash?

(contributed by brian d foy)

There are a couple of ways that you can process an entire hash. You
can get a list of keys, then go through each key, or grab a one
key-value pair at a time.

To go through all of the keys, use the C<keys> function. This extracts
all of the keys of the hash and gives them back to you as a list. You
can then get the value through the particular key you're processing:

   foreach my $key ( keys %hash ) {
      my $value = $hash{$key}
      ...
      }

Once you have the list of keys, you can process that list before you
process the hashh elements. For instance, you can sort the keys so you
can process them in lexical order:

   foreach my $key ( sort keys %hash ) {
      my $value = $hash{$key}
      ...
      }

Or, you might want to only process some of the items. If you only want
to deal with the keys that start with C<text:>, you can select just
those using C<grep>:

   foreach my $key ( grep /^text:/, keys %hash ) {
      my $value = $hash{$key}
      ...
      }

If the hash is very large, you might not want to create a long list of
keys. To save some memory, you can grab on key-value pair at a time
using C<each()>, which returns a pair you haven't seen yet:

   while( my( $key, $value ) = each( %hash ) ) {
      ...
      }

The C<each> operator returns the pairs in apparently random order, so if
ordering matters to you, you'll have to stick with the C<keys> method.

The C<each()> operator can be a bit tricky though. You can't add or
delete keys of the hash while you're using it without possibly
skipping or re-processing some pairs after Perl internally rehashes
all of the elements. Additionally, a hash has only one iterator, so if
you use C<keys>, C<values>, or C<each> on the same hash, you can reset
the iterator and mess up your processing. See the C<each> entry in
L<perlfunc> for more details.