我仍然是perl的初学者,这里我试图遍历$struct->{'transferBatch'}->{'networkInfo'};
并且它的转储看起来像:
$VAR1 = {
'utcTimeOffsetInfo' => [
{
'utcTimeOffset' => '+0100',
'utcTimeOffsetCode' => 0
}
],
'recEntityInfo' => [
{
'recEntityId' => '87.238.128.37',
'recEntityType' => 2,
'recEntityCode' => 0
},
{
'recEntityCode' => 1,
'recEntityType' => 2,
'recEntityId' => '213.233.130.201'
},
{
'recEntityId' => '353876999524',
'recEntityCode' => 1,
'recEntityType' => 1
},
{
'recEntityCode' => 3,
'recEntityType' => 1,
'recEntityId' => '353876999523'
}
]
};
我只想在recEntityCode
处获得recEntityType = 2
并将其存储在可验证的$recEntityCode_2
中,对于recEntityType = 1
$recEntityCode_1
来说也是一样,每个变量只有一个值他们只是先捕捉然后打破循环
#!/usr/bin/perl -w
use strict;
use warnings;
use TAP3::Tap3edit;
use Data::Dumper;
printDir(".");
sub printDir{
opendir(DIR, $_[0]);
my @files;
my @dirs;
(@files) = readdir(DIR);
foreach my $file (@files) {
if (-f $file and substr($file,0,2) eq "CD") {
my $tap3 = TAP3::Tap3edit->new;
my $tap_file = $file;
$tap3->decode($tap_file) or die $tap3->error;
my $struct=$tap3->structure;
my $Tracker = $struct->{'transferBatch'};
if (defined $Tracker){
my $rectag = $struct->{'transferBatch'}->{'networkInfo'}->{'recEntityInfo'};
$count_1=0;
$count_2=0
foreach my $rectag1( @{$rectag} )
{
if ($rectag1->{'recEntityType'} && int($rectag1->{'recEntityType'}) == 2){
$var1_recEntityType = $rectag1->{'recEntityCode'}
$count_1 = $count_1 + 1;
}
if ($rectag1->{'recEntityType'} && int($rectag1->{'recEntityType'}) == 1){
$var1_recEntityType = $rectag1->{'recEntityCode'}
$count_2 = $count_2 + 1;
}
if ($count_1 = 1 && $count_2 = 1)
{
break;
}
}
print $recEntityCode_2;
print$recEntityCode_1;
$tap3->encode("$tap_file") or die $tap3->error;
}
}
}
closedir(DIR);
}
答案 0 :(得分:2)
我不知道是否还有另一种计数器的方法,但是它与我合作:
my $element;
$counter_rec2 = 0;
$counter_rec1 = 0;
foreach $element ( @{$struct->{'transferBatch'}->{'networkInfo'}->{'recEntityInfo'} } ) {
if (defined $element->{recEntityType} && $element->{recEntityType}==2 && $counter_rec2 == 0 ) {
$recEntityCode2=$element->{recEntityCode};
$counter_rec2 = $counter_rec2 +1;
print "recEntityCode: $recEntityCode2\n";
}
if (defined $element->{recEntityType} && $element->{recEntityType}==1 && $counter_rec1 == 0 ) {
$counter_rec1 = $counter_rec1 +1;
$recEntityCode1=$element->{recEntityCode};
print "recEntityCode: $recEntityCode1\n";
}
}
print "this is value for 2 $recEntityCode2\n";
print "this is value for 1 $recEntityCode1\n";
答案 1 :(得分:2)
嗯,有许多解决方案取决于您的实际拥有和想要的(TIMTOWTDI,您知道)。您知道实体类型的确切数目吗?您确定每个实体至少有一个数组元素吗?
下面的代码很脏,只是概念证明,只为给您一个主意,它回答了被问到的字面问题(我假设您的输入哈希引用为$r
):>
no strict;
no warnings;
use List::Util qw(first);
for my $type (1, 2) {
${qq|recEntityCode_$type|} = (first { $_->{recEntityType} == $type } $r->{recEntityInfo}->@*)->{recEntityCode};
}
print $recEntityCode_1 . "\n";
print $recEntityCode_2 . "\n";
可以肯定,我不会使用它。更好的方法是创建一个哈希来存储结果,而不是为每个结果声明单独的变量:
use strict;
use warnings;
use List::Util qw(first);
my %recEntityCodes;
for my $type (1, 2) {
$recEntityCodes{$type} = (first { $_->{recEntityType} == $type } $r->{recEntityInfo}->@*)->{recEntityCode};
}
print $recEntityCodes{1} . "\n";
print $recEntityCodes{2} . "\n";
容易看到它也不是最优的,因为我们从一开始就对每种类型都使用了数组(同样,只是为了演示一种可能的解决方案)。
以下是我能想到的最简单的解决方案:
use strict;
use warnings;
my %recEntityCodes;
$recEntityCodes{$_->{recEntityType}} //= $_->{recEntityCode} for $r->{recEntityInfo}->@*;
print $recEntityCodes{1} . "\n";
print $recEntityCodes{2} . "\n";
这里我们只遍历一个数组,但是另一方面,我们总是遍历整个数组。
哪个是最好的取决于您。如果数组足够短,通常就不在乎了,只需将变量3作为最短的代码即可。如果阵列很大,则变体2或3可能会从阵列属性中获利。如果数组确实很大,则值得进一步优化。