in reply to getting keys of multi-level hashrefs

This little sub will recursively dig through a supplied hashref and print all values.
sub DigThroughHashref { my $hr_data = shift; my @keystack = @_; foreach (keys %{$hr_data}) { if (ref ($hr_data->{$_}) eq "HASH") { print ("Digging through [$_]:\n"); push (@keystack, $_); DigThroughHashref($hr_data->{$_}, @keystack); pop (@keystack); } else { print (join ('->', @keystack) . "->$_ - $hr_data->{$_}\n") +; } } ## end foreach (keys %{$hr_data}) } ## end sub DigThroughHashref
Call it using DigThroughHashref($hashref);

Also, there is an error in your boss_enemies data. There are periods following the attacktype instead of comma's.

You can also use
foreach (keys %{$hashref}) { }
instead of declaring an extra %hash-variable.

Also, you can get to certain values by simply using '->' a lot: printing $hashref->{items}->{armor}->{helm}->{body_part} will print 'head'.
(This is basically what DigThroughHashref does).

Edit: forgot ->$_ in the output

Replies are listed 'Best First'.
Re^2: getting keys of multi-level hashrefs
by cdarke (Prior) on Jul 07, 2010 at 10:13 UTC
    When dealing with a large hash (the OP stated this was a small example) it may be better to use each rather than getting the overhead of a temporary list using keys. A skelton example:
    while (my ($key,$value) = each %$hashref) { print "$key $value\n"; }
      Though I doubt the overhead will have a significant impact, even with really large hashes, using each is indeed more optimized.
      That, and another optimization I thought of after posting my code, would change the subroutine to:
      sub DigThroughHashref { my $hr_data = shift; while (my ($key, $value) = each %{$hr_data}) { if (ref ($value) eq "HASH") { print ("Digging through [$key]:\n"); DigThroughHashref($value, @_, $key); } else { print (join ('->', @_) . "->$key - $value\n"); } } ## end while (my ($key, $value) ... } ## end sub DigThroughHashref
      All occurrances of $_ are now replaced by $key, and all occurrances of $hr_data->{$_} are now replaced by $value.
      Also, the seperate variable @keystack is now optimized out. Instead of pushing the to-be-parsed key explicitly onto the end of @keystack, it is now simply added to the arguments of the sub (which results in it being added to @_ inside the sub).
        Thank you so much for responding so quickly the first time. I was able to see your post before your first edit, after experimenting a bit it's safe to say I learned alot from that. Thank you also for taking your time to optimize that sub.