Re: Extracting values from nested hashrefs
by choroba (Cardinal) on Sep 12, 2012 at 09:13 UTC
|
I am not sure whether map plus double values counts as implicit traversing:
say for map values %$_, values %$animals;
Update: simplified.
| [reply] [d/l] |
|
my $animals = {
gnu => {
humps => 0,
mascot_for => 'emacs',
},
dromedary => {
humps => 1,
mascot_for => 'perl',
},
camel => {
humps => 2,
mascot_for => 'perl',
},
};
BTW, implicit traversing is OK; I just wanted to avoid some sort of loop with , say while.
Thanks,
loris | [reply] [d/l] [select] |
|
map $_->{humps}, values %$animals;
If your structure becomes even more complicated (e.g. different level of nesting), you should use recursion (or CPAN).
| [reply] [d/l] |
|
#! perl
use strict;
use warnings;
use Data::Dumper;
my $animals = {
gnu => {
humps => 0,
mascot_for => 'emacs',
},
dromedary => {
humps => 1,
mascot_for => 'perl',
},
camel => {
humps => 2,
mascot_for => 'perl',
},
};
my $flat = Dumper($animals);
print "$1\n" while $flat =~ / 'humps' \s+ => \s+ (\d+) /gx;
Output:
2
0
1
TMTOWTDI.
Athanasius <°(((>< contra mundum
| [reply] [d/l] [select] |
Re: Extracting values from nested hashrefs
by kcott (Archbishop) on Sep 12, 2012 at 09:25 UTC
|
G'day loris,
Hash keys have no inherent order. If you want to retain the order you've shown, you'll need to specify it explicitly.
Here's two solutions in the one script. Pick whichever is most appropriate for you.
#!/usr/bin/env perl
use 5.010;
use strict;
use warnings;
my $animals = {
gnu => {
humps => 0,
},
dromedary => {
humps => 1,
},
camel => {
humps => 2,
},
};
my @humps;
push @humps, $_->{humps} for map { $animals->{$_} } keys %$animals;
say "Unsorted humps: @humps";
my @sorted_animals = qw{gnu dromedary camel};
my @sorted_humps;
push @sorted_humps, $_->{humps} for map { $animals->{$_} } @sorted_ani
+mals;
say "Sorted humps: @sorted_humps";
Outputs:
$ pm_nested_hash_extract.pl
Unsorted humps: 2 0 1
Sorted humps: 0 1 2
| [reply] [d/l] [select] |
|
The ordering happens to be irrelevant, so the unsorted version is fine. I
see from your solution that the distinction I was trying to make between
explicit and implicit was a bit foolish. What I meant was that I
wanted to do things in a nifty perl-like way, as you have done, rather than in a dull, C-like way.
Thanks, loris
| [reply] |
|
Why be more cryptic that you need to be?
Doing so will not be more efficient.
#!/usr/bin/perl -w
use strict;
my $animals = {
gnu => {
humps => 0,
mascot_for => 'emacs',
},
dromedary => {
humps => 1,
mascot_for => 'perl',
},
camel => {
humps => 2,
mascot_for => 'perl',
},
};
foreach my $critter (keys %$animals)
{
print "$critter "; #camel gnu dromedary
}
print "\n";
foreach my $critter (keys %$animals) #sort if you want to
{
print "$animals->{$critter}{humps} "; #2 0 1
}
print "\n";
| [reply] [d/l] |
Re: Extracting values from nested hashrefs
by trizen (Hermit) on Sep 12, 2012 at 13:39 UTC
|
use 5.010;
my $animals = {
gnu => {
humps => 0,
mascot_for => 'emacs',
},
dromedary => {
humps => 1,
zzz => {
humps => 'nested',
aaa => {
humps => 'really nested',
xxx => 0,
},
},
mascot_for => 'perl',
},
};
sub print_humps {
my $hash_ref = shift;
foreach my $key (keys %{$hash_ref}) {
if (ref $hash_ref->{$key} eq "HASH") {
print_humps($hash_ref->{$key});
}
elsif ($key eq 'humps') {
say $hash_ref->{$key};
}
}
}
print_humps($animals);
__END__
0
1
nested
really nested
| [reply] [d/l] |
Re: Extracting values from nested hashrefs
by tobyink (Canon) on Sep 12, 2012 at 14:38 UTC
|
use strict;
use warnings;
use Test::More;
use B::Deparse;
my $animals;
my $deparse = B::Deparse->new;
$deparse->ambient_pragmas(strict => 'all', warnings => 'all');
# Function to check that each solution works!
sub this_works (&)
{
$animals = {
gnu => {
humps => 0,
},
dromedary => {
humps => 1,
},
camel => {
humps => 2,
},
};
my @results = $_[0]->();
my $code = $deparse->coderef2text($_[0]);
if (is_deeply [sort @results], [qw/ 0 1 2 /] )
{
diag "this works $code";
}
else
{
diag "FAILED! $code";
}
}
this_works {
map($_->{humps}, values %$animals)
};
this_works {
map { $_->{humps} } values %$animals
};
this_works {
map { $animals->{$_}{humps} } keys %$animals
};
this_works {
require JSON::Path;
JSON::Path->new('$..humps')->values($animals);
};
done_testing();
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
| [reply] [d/l] |
Re: Extracting values from nested hashrefs
by jdporter (Paladin) on Sep 12, 2012 at 13:58 UTC
|
| [reply] |