用perl遍历结构

时间:2019-11-25 14:55:56

标签: perl

我仍然是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);
}

2 个答案:

答案 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可能会从阵列属性中获利。如果数组确实很大,则值得进一步优化。