我们如何检索Perl中Hash of Hash中的键值?
我试着使用键功能。我想删除重复项,然后对它们进行排序,我可以
使用uniq
和sort
函数。我错过了什么吗?
#!/usr/bin/perl
use warnings;
use strict;
sub ids {
my ($data) = @_;
my @allID = keys %{$data};
my @unique = uniq @allID;
foreach ( @unique ) {
@allUniqueID = $_;
}
my @result = sort{$a<=>$b}(@allUniqueId);
return @result;
}
my $data = {
'first' => {
'second' => {
'third1' => [
{ id => 44, name => 'a', value => 'aa' },
{ id => 48, name => 'b', value => 'bb' },
{ id => 100, name => 'c', value => 'cc' }
],
id => 19
},
'third2' => [
{ id => 199, data => 'dd' },
{ id => 40, data => 'ee' },
{ id => 100, data => { name => 'f', value => 'ff' } }
],
id => 55
},
id => 1
};
# should print “1, 19, 40, 44, 48, 55, 100, 199”
print join(', ', ids($data)) . "\n";
我知道它不完整,但我不知道该怎么办。任何帮助将不胜感激。
答案 0 :(得分:2)
此例程将递归遍历数据结构并提取与散列键id
对应的所有值,而不对结果进行排序或消除重复:
sub all_keys {
my $obj = shift;
if (ref $obj eq 'HASH') {
return map {
my $value = $obj->{$_};
$_ eq 'id' ? $value : ref $value ? all_keys($value) : ();
} keys %$obj;
} elsif (ref $obj eq 'ARRAY') {
return map all_keys($_), @$obj;
} else {
return;
}
}
要进行排序/删除,只需将其命名为:
my @ids = sort { $a <=> $b } uniq(all_ids($data));
(我假设uniq
例程在别处定义。)
答案 1 :(得分:0)
这是我的递归方法版本
use warnings;
use strict;
sub ids {
my ($data) = @_;
my @retval;
if (ref $data eq 'HASH') {
push @retval, $data->{id} if exists $data->{id};
push @retval, ids($_) for values %$data;
}
elsif (ref $data eq 'ARRAY') {
push @retval, ids($_) for @$data;
}
@retval;
}
my $data = {
'first' => {
'second' => {
'third1' => [
{ id => 44, name => 'a', value => 'aa' },
{ id => 48, name => 'b', value => 'bb' },
{ id => 100, name => 'c', value => 'cc' }
],
id => 19
},
'third2' => [
{ id => 199, data => 'dd' },
{ id => 40, data => 'ee' },
{ id => 100, data => { name => 'f', value => 'ff' } }
],
id => 55
},
id => 1
};
my @ids = sort { $a <=> $b } ids($data);
print join(', ', @ids), "\n";
<强>输出强>
1, 19, 40, 44, 48, 55, 100, 100, 199
<强>更新强>
上面解决方案中的大部分代码用于解决如何从数据引用中提取值列表的问题。 Perl的最新版本有一个实验工具,允许您在哈希和数组上使用values
运算符,也可以在引用ro两者上使用,因此,如果您正在运行Perl 5的版本14或更高版本,并且舒服地禁用实验性警告,然后您可以这样写ids
use warnings;
use strict;
use 5.014;
sub ids {
my ($data) = @_;
return unless my $type = ref $data;
no warnings 'experimental';
if ( $type eq 'HASH' and exists $data->{id} ) {
$data->{id}, map ids($_), values $data;
}
else {
map ids($_), values $data;
}
}
输出与先前解决方案的输出相同