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]