Rob Dixon wrote:
> John W. Krahn wrote:
> > 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.
>
> As far as I knew this was only a problem with iterating using
>
> while (my ($k, $v) = each %hash) {
> :
> }
>
> if instead you do
>
> foreach (keys %hash) {
> :
> }
>
> it's the same as doing
>
> my @keys = keys %hash;
> foreach (@keys) {
> :
> }
>
> which would be fine here. I would write some code to check but
> it's not going to happen tonight!
OK, I did do it tonight! It's not conclusive, but this code works.
Any thoughts anybody?
Cheers,
Rob
use strict;
use warnings;
my %hash = (a => 1, b => 2, c => 3);
my ($k, $v) = (d => 4);
$hash{$k++} = $v++ foreach keys %hash;
print $_, " => ", $hash{$_}, "\n" foreach sort keys %hash;
OUTPUT
a => 1
b => 2
c => 3
d => 4
e => 5
f => 6
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]