如何在perl数据结构中获取一个键的所有值?
我想写一个函数,它将返回下面任何级别的数据结构中所有“id”值的列表,按数字排序。此外,如果在数据结构中的多个位置发现相同的值,则该值只应包含在返回的列表中一次如何在perl数据结构中获取一个键的所有值?,perl,hash,Perl,Hash,我想写一个函数,它将返回下面任何级别的数据结构中所有“id”值的列表,按数字排序。此外,如果在数据结构中的多个位置发现相同的值,则该值只应包含在返回的列表中一次 sub ids { my ($data) = @_; # Define this function } my $data = { 'top' => { 'window' => {
sub ids {
my ($data) = @_;
# Define this function
}
my $data = {
'top' => {
'window' => {
'elements' => {
{ id => 44, name => 'link', value => 'www.cnn.com' },
{ id => 48, name => 'title', value => 'CNN Home Page' },
{ id => 100, name => 'author', value => 'Admin' }
},
id => 19
},
'cache' => {
{ id => 199, data => '5' },
{ id => 40, data => '9' },
{ id => 100, data => { name => 'author', value => 'Admin' }
}
},
id => 55
},
id => 1
};
# should print “1, 19, 40, 44, 49, 55, 100, 199”
print join(', ', ids($data)) . “\n”;
一些数据结构应该是数组,而不是OP中的散列
use strict;
use warnings;
sub ids_r {
my ($data) = @_;
return map {
my $r = ref($data->{$_});
$r eq "HASH" ? ids_r($data->{$_}) :
$r ? map ids_r($_), @{$data->{$_}} :
$_ eq "id" ? $data->{$_} :
();
} keys %$data;
}
sub ids {
my ($data) = @_;
my %seen;
return
sort { $a <=> $b }
grep !$seen{$_}++, ids_r($data);
}
my $data = {
'top' => {
'window' => {
'elements' => [
{ id => 44, name => 'link', value => 'www.cnn.com' },
{ id => 48, name => 'title', value => 'CNN Home Page' },
{ id => 100, name => 'author', value => 'Admin' }
],
id => 19
},
'cache' => [
{ id => 199, data => '5' },
{ id => 40, data => '9' },
{ id => 100, data => { name => 'author', value => 'Admin' } }
],
id => 55
},
id => 1
};
print join(', ', ids($data));
这里有一个简单的递归解决方案。很容易看出这里发生了什么
# There is a faster version of `uniq` provided by List::MoreUtils on CPAN.
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
sub ids {
my $val = shift;
my $ref = ref $val;
my @r;
if ($ref eq 'HASH')
{
@r = map ids($_), grep ref, values(%$val);
push @r, $val->{id} if exists $val->{id};
}
elsif ($ref eq 'ARRAY')
{
@r = map ids($_), grep ref, @$val;
}
sort { $a <=> $b } uniq(@r);
}
$data不包含有效的Perl数据结构,例如,元素的值是多少?也许多个排序不会提高效率。@mpapec-您的答案也是如此。我说的是在递归函数中使用排序。@mpapec,我也是。您有相互递归的函数。我猜是偶然的。
# There is a faster version of `uniq` provided by List::MoreUtils on CPAN.
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
sub ids {
my $val = shift;
my $ref = ref $val;
my @r;
if ($ref eq 'HASH')
{
@r = map ids($_), grep ref, values(%$val);
push @r, $val->{id} if exists $val->{id};
}
elsif ($ref eq 'ARRAY')
{
@r = map ids($_), grep ref, @$val;
}
sort { $a <=> $b } uniq(@r);
}
# There is a faster version of `uniq` provided by List::MoreUtils on CPAN.
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
sub ids {
my @r;
while (@_) {
my $val = shift;
my $ref = ref($val);
if ($ref eq 'HASH')
{
push @r, $val->{id} if exists $val->{id};
push @_, grep ref, values %$val;
}
elsif ($ref eq 'ARRAY')
{
push @_, grep ref, @$val;
}
}
sort { $a <=> $b } uniq(@r);
}