我必须迭代perl中的嵌套哈希并执行一些操作。我的结构是
$featureGroup = [
{
featureType => "widget",
name => "dpx-shadow-fleet",
parameterMap => { dpxContext => "shadowAtf", dpxEndPoint => "/art/dp/ppd?" },
},
{
featureType => "widget",
name => "dpx-shadow-fleet",
parameterMap => { dpxContext => "shadowBtf", dpxEndPoint => "/art/dp/btf?" },
},
{
features => [
{
featuredesc => [
{
critical => 1,
featureType => "widget",
name => "dpx-ppd",
parameterMap => { dpxContext => "atf", dpxEndPoint => "/art/dp/" },
},
{
featureType => "widget",
name => "error",
parameterMap => { errorMessageId => "error" },
},
],
featureType => "sequence",
},
{
critical => 1,
features => ["encode-landing-image", "image-encoding-error"],
featureType => "sequence",
},
],
handler => "/gp/product/features/embed-landing-image.mi",
name => "embed-landing-image",
pfMetrics => { "" => undef, "start" => sub { "DUMMY" }, "stop" => sub { "DUMMY" } },
type => "custom-grid",
},
];
我想遍历featuredesc子阵列并获取值名称。我正在尝试这个。
for(my $i = 0; $i < @$featureGroup; $i++){
if(defined $featureGroup->[$i]->{'features'}){
for(my $j = 0; $j < @$featureGroup->[$i]->{'features'} ; $j++){
print "$featureGroup->[$i]->{'features'}->{'featuredesc}->{name}";
}
}
}
但这不起作用。我不明白我哪里错了。正确方向的任何指针都很有用。
答案 0 :(得分:1)
你有一个非常复杂的数据对象,你已经遇到过处理它的问题。虽然我可以帮助您解决直接问题,但我认为您将从学习如何降低复杂性中获益更多。
Perl支持面向对象的编程。这允许您获取数据结构并将子例程附加到对它们进行操作的子例程。您可以阅读有关Perl OO here的信息。我将快速向您展示如何将$featureGroup
列表转换为对象列表,以及如何访问单个对象包含的features
。您应该将此技术应用于数据结构中的每个哈希值(如果您确定某些内部哈希值不应该是对象,则可以将其调整回来,但最好先过度使用它然后缩小而不是反过来)。
这是功能组哈希之一:
{
'featureType' => 'widget',
'name' => 'dpx-shadow-fleet',
'parameterMap' => {
'dpxContext' => 'shadowAtf',
'dpxEndPoint' => '/art/dp/ppd?'
}
}
在这一个中,您有featureType
,name
和parameterMap
。这些字段不会出现在列表中的每个对象中(事实上,最后一个哈希值与前两个哈希值完全不同)。我将向您展示如何创建一个需要这三个参数的对象:
package Feature;
use Moose; # You may have to install this
has 'featureType' => (
'is' => 'rw',
'isa' => 'Str'
);
has 'name' => (
'is' => 'rw',
'isa' => 'Str'
);
has 'parameterMap' => (
'is' => 'rw',
'isa' => 'HashRef'
# You could make this accept another object type
# if you convert this inner hash
);
然后您可以像这样构建对象:
my $f = new Feature(
'featureType' => 'widget',
'name' => 'dpx-shadow-fleet',
'parameterMap' => {
'dpxContext' => 'shadowAtf',
'dpxEndPoint' => '/art/dp/ppd?'
}
);
然后,您可以使用命名的访问者访问这些字段:
print $f->name; # dpx-shadow-fleet
目前这似乎是一种使用哈希的更长方式,对吧?那么真正的好处来自于能够在类上定义任意子程序,从而隐藏调用者的复杂性。因此,您希望在原始问题中对features
数组进行操作。让我们将其定义为一个字段:
has features => (
is => 'rw',
isa => 'ArrayRef[HashRef]'
# This is an array containing hashes
# You _really_ want to turn the inner hashes into an object here!
);
然后我们可以在另一个子程序中对它们进行操作。让我们定义一个返回作为序列的每个特征(具有featureType
序列)的那个:
sub get_sequences {
my ($self) = @_;
return grep { $_->{featureType} eq 'sequence' } @{ $self->features };
}
现在,当您使用此类型的对象来获取序列功能时,您需要做的就是:
$f->get_sequences();
如果将此应用于哈希的所有级别,您会发现代码变得更容易管理。祝你好运!
答案 1 :(得分:0)
试试这个:
for(my $i = 0; $i < @$featureGroup; $i++){
if(defined $featureGroup->[$i]->{'features'}){
for(my $j = 0; $j<scalar @{$featureGroup->[$i]->{'features'}} ; $j++){
for(my $k=0;$k<scalar @{$featureGroup->[$i]->{'features'}->[$j]->{'featuredesc'}};$k++) {
if (defined $featureGroup->[$i]->{'features'}->[$j]->{'featuredesc'}->[$k]->{'name'}) {
print $featureGroup->[$i]->{'features'}->[$j]->{'featuredesc'}->[$k]->{'name'}."\n";
}
}
last if !defined $featureGroup->[$i+1]->{'features'};
}
}
}
答案 2 :(得分:0)
不是按索引迭代,而是建议您按元素迭代。
这使您可以使用grep
或next
for my $group (grep {$_->{features}} @$featureGroup) {
for my $feature (grep {$_->{featuredesc}} @{$group->{features}}) {
for my $desc (@{$feature->{featuredesc}}) {
print "$desc->{name}\n"
}
}
}
输出:
dpx-ppd
error