Reputation: 91
I'm just learning perl.
I am trying to rewrite this multilevel loop using temporary variables so that i do not require the previous keys ($key1
$key2
) to gain access(dereferencing) to $key3
. What would be the easiest way of doing this. Thanks.
for my $key1 ( keys %foo )
{
for my $key2 ( keys %{$foo{$key1}} )
{
for my $key3 ( keys %{$foo{$key1}{$key2}} )
Upvotes: 3
Views: 238
Reputation: 107040
I'm just learning perl.
And you're already doing references. That's pretty good.
I am trying to rewrite this multilevel loop using temporary variables so that I do not require the previous keys ($key1 $key2) to gain access(dereferencing) to $key3. What would be the easiest way of doing this.
If I think I understand what you're saying, you want to be able to find all of the third level hash keys without going through all the first and second level hash keys.
Let's say that %foo
has keys:
$foo{one}->{alpha}->{apple};
$foo{one}->{alpha}->{berry};
$foo{one}->{beta}->{cucumber};
$foo{one}->{beta}->{durian};
$foo{two}->{uno}->{eggplant};
$foo{two}->{uno}->{fig};
$foo{two}->{dos}->{guava};
$foo{two}->{dos}->{honeydew};
By the way, I like the ->
syntax simply because it reminds me I'm dealing with references to something and not an actual hash. It helps me see the issue a bit clearer.
You want to go through the keys of vegetable and fruit names without going through the first two levels. Is that correct?
Here the ->
syntax helps clarify the answer. These eight keys belong to four separate hashes:
$foo{one}->{alpha};
$foo{one}->{beta};
$foo{two}->{uno};
$foo{two}->{dos};
And, the hashes they're in are anonymous, that is there's no variable name that contains these hashes. The only way I can access these hashes is to locate the four hashes that contain them.
However, these four keys themselves are stored into two separate hashes. I need to find those two hashes to find their keys. Again, these two hashes are anonymous. Again, the only way I can find them is to know the two hashes that contain them:
$foo{one};
$foo{two};
So, in order to find my third level values, I need to know the second level hashes that contain them. In order to find those second hashes, I need to find the first level keys that contain them.
However, if you have some sort of known structure, you may already know the keys you need in order to find the values you're looking for.
Imagine something like this:
$person{$ssn}->{NAME}->{FIRST} = "Bob";
$person{$ssn}->{NAME}->{MI} = "Q.";
$person{$ssn}->{NAME}->{LAST} = "Smith";
Here I can go directly through to the first, last, and middle initial of each person. All I have to do is go through the various social security numbers:
for my $ssn ( sort keys %person ) {
say "My name is " . $person{$ssn}->{NAME}->{FIRST}
. " " . $person{$ssn}->{NAME}->{MI}
. " " . $person{$ssn}->{NAME}->{LAST};
}
Upvotes: 1
Reputation: 24063
You can use while
and each
like this:
while (my ($key1, $inner_hash) = each %foo) {
while (my ($key2, $inner_inner_hash) = each %$inner_hash) {
while (my ($key3, $value) = each %$inner_inner_hash) {
print $value;
}
}
}
This approach uses less memory than foreach keys %hash
, which constructs a list of all the keys in the hash before you begin iterating. The drawback with each
is that you cannot specify a sort order. See the documentation for details.
Upvotes: 5
Reputation: 133
How about this:
foreach(values %foo){
foreach(values %$_){
foreach my $key3 (keys %$_){
print $key3;
}
}
}
Upvotes: 2
Reputation: 22262
You're looking for something like this:
for my $key1 ( keys %foo )
{
my $subhash = $foo{$key1};
for my $key2 ( keys %$subhash )
{
my $subsubhash = $subhash->{$key2};
for my $key3 ( keys %$subsubhash )
Upvotes: 4