Rob Dixon wrote:
> 
> Well done Kevin!
> 
> Just a couple of points.
> 
> Kevin Pfeiffer wrote:
> >
> > (I noticed that, too.) But thanks to your tip I think I've created
> > my first recursive sub-routine (only tested on this example). If it
> > does what the OP requested (and y'all don't find too much wrong
> > with it) then I'm a happy man!
> >
> > pad_keys($self);
> > print Dumper(\$self);
> >
> > sub pad_keys {
> >    my $ref = shift;
> >    if (ref $ref eq "HASH") {
> >       for my $value (%$ref) {
> 
> This will loop over all the keys and values in the
> hash, in the order key1, value1, key2, value2, ...
> All you want is the values.
> 
> >          if (ref $value eq "HASH") {
> >             pad_keys($value);
> >          }
> >       }
> >       for (keys %$ref) {
> >          my $old = $_;
> >          tr/ /_/;
> >          $ref->{$_} = $ref->{$old};
> 
> You ought to check whether the new key already exists, otherwise you're
> going o be losing data.
> 
> >          delete $ref->{$old};
> >       }
> >    }
> > }
> 
> Finally, there's no need process the values and then the keys
> in separate loops. Each execution of either loop corresponds to
> a key/value pair so you can write
> 
>   foreach (keys) {
>     modify key;
>     recurse on value;
>   }
> 
> This is what I came up with. It skips the rest of the loop
> if the new key is the same as the old one, and uses the
> fact that 'delete' returns the value of the element it
> deleted.
> 
>   sub pad_keys {
>     my $ref = shift;
>     return unless ref $ref eq 'HASH';
>     foreach (keys %$ref) {
>       pad_keys($ref->{$_});
>       next unless (my $new = $_) =~ tr/ /_/;
>       if (exists $ref->{$new}) {
>         warn "Padded key $new already exists";
>       }
>       else {
>         $ref->{$new} = delete $ref->{$_};
>       }
>     }
>   }

Kevin and Rob,

perldoc -q "add or remove keys from a hash"

Found in /usr/lib/perl5/5.6.0/pod/perlfaq4.pod
       What happens if I add or remove keys from a hash while
       iterating over it?

       Don't do that. :-)

       [lwall] In Perl 4, you were not allowed to modify a hash
       at all while iterating over it.  In Perl 5 you can delete
       from it, but you still can't add to it, because that might
       cause a doubling of the hash table, in which half the
       entries get copied up to the new top half of the table, at
       which point you've totally bamboozled the iterator code.
       Even if the table doesn't double, there's no telling
       whether your new entry will be inserted before or after
       the current iterator position.

       Either treasure up your changes and make them after the
       iterator finishes, or use keys to fetch all the old keys
       at once, and iterate over the list of keys.


John
-- 
use Perl;
program
fulfillment

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to