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]