Reputation: 136
@a=("f","a","b");
$K{"f"}{"aa"}=1;
$K{"a"}{"aa"}=1;
$k{"b"}{"bb"}=1;
foreach(@a){
@c= sort keys %{$k{$_}};
}
print "@c\n";
foreach(@c) {...}
perl hash_test.pl
bb
I want to keep the keys of the hash into an array, so that I can use the array as an input for the following statements.
But it seemed that the assay @c
just only hold the last element.
Could anyone tell me why or help me to improve the script?
Upvotes: 1
Views: 96
Reputation: 66883
You assign the array every time in the foreach
, thus overwriting it every time. So you end up with only having the last thing assigned to it. If you move the print
inside the foreach
you'll see that they are all there.
To store those keys you need to add them to the array, not assign the array. I've corrected the typo $k
to $K
, and changed aa
that goes with f
to ff
(expecting it to be a typo as well).
my @c;
foreach my $el (@a) {
push @c, sort keys %{$K{$el}};
}
print "@c\n";
This prints the line: ff aa bb
. Every time through the loop all keys found in the hash for a particular array element are added to @c
, each as a separate element. So @c
will contain all bottom-level keys across the whole data structure.
However, there is more that I would like to suggest.
Always use strict;
and use warnings;
This is not pedantry but it directly helps. I never write code without them. The typo would be caught here, for example.
Use descriptive variable names. Specifically, single-letter variable names are just too easy to confuse, unless in very short loops or where it is crystal clear what they are. (For example, a typo like this couldn't really happen.) Most importantly, the code is going to be far nicer to work with. That generally results in better code.
Please use good indentation and spacing. It helps a lot, in many ways.
A useful core package for nested data structures is Data::Dumper, which can print the whole thing nicely formatted so we can see it. Try to add to the end of your code
use Data::Dumper;
print Dumper(\%K);
There are yet others that do the same or similar.
Here is another way to do what you ask.
my @lowest_keys = map { sort keys %{$K{$_}} } @a;
I call them lowest_keys
to emphasize that these are the ones from the last hash in your data structure, the bottom of it. The map applies processing in the block { ... }
to each element of @a
in turn, returning a list with all these results. (If any one result itself is a list, with more elements than one, it gets merged into the overall output list. So this may create the output list with many more elements than the input.) This list can then be assigned to an array, as above, or passed on to another function that expects a list as input, or interated over.
The map
is generally used to transform an array into another, by doing to each element what is in { ... }
block. Its close cousin grep is used to filter, so passing through only the elements of the input list for which the condition in { ... }
evaluates to true, forming the output list. For example, filter out undefined array elements: my @good = grep { defined } @all
Upvotes: 5
Reputation:
Variable names are case sensitive, so %K... and %k... are not the same. Always use
use strict;
use warnings;
and declare your variables with my
. That prevents you from making this kind of mistakes.
Upvotes: 3