Perl哈希表的哈希表和计数

4

我正在尝试处理一个使用Data::Dumper输出的Perl数据结构

$VAR1 = 'GAHD';
$VAR2 = [
    {   'COUNTRY'       => 'US',
        'NAME'          => 'K. Long',
        'DATE_OF_BIRTH' => '7/27/1957',
        'POSITION'      => 'SENIOR OFFICER',
        'AGE'           => 57,
        'GRADE'         => 'P5'
    },
    {   'COUNTRY'       => 'US',
        'NAME'          => 'J. Buber',
        'DATE_OF_BIRTH' => '12/11/1957',
        'POSITION'      => 'CHIEF',
        'GRADE'         => 'D1'
    },
    {   'COUNTRY'       => 'US',
        'NAME'          => 'M. Amsi',
        'DATE_OF_BIRTH' => '1/1/1957',
        'POSITION'      => 'SENIOR ANIMAL HEALTH OFFICER',
        'AGE'           => 57,
        'GRADE'         => 'P5'
    },
    {   'COUNTRY'       => 'US',
        'NAME'          => 'E. Xenu',
        'DATE_OF_BIRTH' => '8/31/1964',
        'POSITION'      => 'SENIOR OFFICER',
        'AGE'           => 50,
        'GRADE'         => 'P5'
    },
];
$VAR3 = 'GAGD';
$VAR4 = [
    {   'COUNTRY'       => 'US',
        'NAME'          => 'P. Cheru',
        'DATE_OF_BIRTH' => '6/18/1966',
        'POSITION'      => 'ANIMAL PRODUCTION OFFICER',
        'AGE'           => 48,
        'GRADE'         => 'P4'
    },
    {   'COUNTRY'       => 'US',
        'NAME'          => 'B. Burns',
        'DATE_OF_BIRTH' => '2/4/1962',
        'POSITION'      => 'ANIMAL PRODUCTION OFFICER',
        'AGE'           => 52,
        'GRADE'         => 'P4'
    },
    {   'COUNTRY'       => 'US',
        'NAME'          => 'R. Mung',
        'DATE_OF_BIRTH' => '12/13/1968',
        'POSITION'      => 'ANIMAL PRODUCTION OFFICER',
        'AGE'           => 45,
        'GRADE'         => 'P4'
    },
    {   'COUNTRY'       => 'GERMANY',
        'NAME'          => 'B. Scherf',
        'DATE_OF_BIRTH' => '8/31/1964',
        'POSITION'      => 'ANIMAL PRODUCTION OFFICER',
        'AGE'           => 50,
        'GRADE'         => 'P4'
    },
    {   'COUNTRY'       => 'GERMANY',
        'NAME'          => 'I. Hoffmann',
        'DATE_OF_BIRTH' => '2/21/1960',
        'POSITION'      => 'CHIEF',
        'AGE'           => 54,
        'GRADE'         => 'P5'
    },
];

以下是输出结果:
1 ADG JUNIOR OFFICER K. King
1 DG SENIOR DIRECTOR K. King
3 P5 SENIOR OFFICER R. Forest
           R.Forest
           K. King
1 P3 JUNIOR OFFICER K. King
3 P1 FORESTRY OFFICER P. Smith
           T. Turner
           K. Turner
1 P1 GENERAL OFFICER K. King

我希望能按部门计算 GRADEPOSITION 的数量。这是我迄今为止编写的代码:
```

以下是我目前整理出来的代码:

```
#Push data read from a flat file and while loop
push @{ $grades{ $_->{GRADE} }{ $_->{POSITION} } }, $_->{NAME} for @$AG;
for my $key (
    sort { substr( $a, 0, 1 ) cmp substr( $b, 0, 1 ) || substr( $b, 0, 2 ) cmp substr( $a, 0, 2 ) }
    keys %grades
    )
{
    for my $pos ( sort { $a cmp $b } keys %{ $grades{$key} } ) {
        my $names = $grades{$key}->{$pos};
        my $count = scalar @$names;

        print $count, ' ', $key, ' ', $pos, ' ', $names->[0], "\n";
        print '        ', $names->[$_], "\n" for 1 .. $#$names;
    }
}

如果另一个部门中出现重复的POSITIONS和GRADES数据(例如P1,高级官员),则该代码将停止输出结果。

我不知道如何通过Division(即GAGD,GAGHD等)访问Hash of Hash,以便每个Division输出相同的GRADEs和POSITIONs。

这是我真正需要的:

**GAGD**
1 ADG JUNIOR OFFICER K. King
1 DG SENIOR DIRECTOR K. King
3 P5 SENIOR OFFICER R. Forest
           R.Forest
           K. King
1 P3 JUNIOR OFFICER K. King
3 P1 FORESTRY OFFICER P. Smith
           T. Turner
           K. Turner
1 P1 GENERAL OFFICER K. King

**GAGHD**
1 P3 JUNIOR OFFICER P. Green
3 P1 FORESTRY OFFICER R. Brown
           F. Boo
           K. Church
1 P1 GENERAL OFFICER D. Peefer

etc.
etc.

1
可能有助于明确你的输入是什么,你的预期输出应该是什么,以及你正在得到的实际输出。这个问题接近于清晰,但仍然非常模糊。 - Nathaniel Ford
你的“what you really need”结果中的“GAGHD”是从哪里来的?这是打错了吗? - i alarmed alien
http://www.perlmonks.org/?node_id=1100124 - choroba
@PerlGui,PerlMonks是否解决了你的问题,还是你仍在思考中? - i alarmed alien
2个回答

3

看起来你想通过除法对信息进行哈希,然后按年级+职位计算和存储名称。以下内容似乎适用于我:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my %grades = (
    GAHD => [ {
               NAME => 'K. Long',
               POSITION => 'SENIOR OFFICER',
               GRADE => 'P5'
              },
              {
               NAME => 'J. Buber',
               POSITION => 'CHIEF',
               GRADE => 'D1'
              },
              {
               NAME => 'M. Amsi',
               POSITION => 'SENIOR ANIMAL HEALTH OFFICER',
               GRADE => 'P5'
              },
              {
               NAME => 'E. Xenu',
               POSITION => 'SENIOR OFFICER',
               GRADE => 'P5'
              },
            ],
    GAGD => [
             {
              NAME => 'P. Cheru',
              POSITION => 'ANIMAL PRODUCTION OFFICER',
              GRADE => 'P4'
             },
             {
              NAME => 'B. Burns',
              POSITION => 'ANIMAL PRODUCTION OFFICER',
              GRADE => 'P4'
             },
             {
              NAME => 'R. Mung',
              POSITION => 'ANIMAL PRODUCTION OFFICER',
              GRADE => 'P4'
             },
             {
              NAME => 'B. Scherf',
              POSITION => 'ANIMAL PRODUCTION OFFICER',
              GRADE => 'P4'
             },
             {
              NAME => 'I. Hoffmann',
              POSITION => 'CHIEF',
              GRADE => 'P5'
             },
            ]);

for my $division (keys %grades) {
    say "**$division**";
    my %group;
    for my $person (@{ $grades{$division} }) {
        my $position = join ' ', @{ $person }{qw{GRADE POSITION}};
        push @{ $group{$position} }, $person->{NAME};
    }

    for my $position (keys %group) {
        say join ' ', scalar @{ $group{$position} },
                      $position,
                      $group{$position}[0];
        my @remaining_names = @{ $group{$position} };
        shift @remaining_names;
        say "\t$_" for @remaining_names;
    }
    say q();
}

更新

如果你在数组引用中存储一个人的姓名以外的更多信息(例如push push @{ $group{$position} }, [ ... ];),可以通过解除引用每个引用来检索它,例如在map中:

    say join ' ', scalar @{ $group{$position} },
                  $position,
                  join "\n\t", map "@$_", @{ $group{$position} };

计数可以来自于$count{$position}{names}中的名称数量。 - i alarmed alien
@PerlGui:将需要打印的所有内容push进去,然后再进行打印。 - choroba
@Choroba,如果我按照您的建议推送数据(即 push @{ $group{$position} }, $person->{NAME},$person->{COUNTRY},$person->{DATE_OF_BIRTH},$person->{AGE},$person->{FEMALE},$person->{VACANT};),那么计数器将无法按预期工作。D1 CHIEF T. Roth 美国 12/11/1937 5621 P5 SENIOR OFFICER K. Logh 英国 7/27/1957 57
  • 我做错了什么?
- Perl Gui
@Choroba,我已经按照建议完成了,并能够打印出哈希元素(例如,push @{ $group{$position} },$rec=[$person->{PWD},$person->{NAME},$person->{COUNTRY},$person->{DATE_OF_BIRTH},$person->{AGE},$person->{FEMALE},$person->{VACANT}])。唯一不起作用的是将哈希元素与计数、等级、位置一起打印出来(例如,say join ' ', scalar @{ $group{$position} }, $position, $group{$position}[0];)。我总是得到1 D1 CHIEF ARRAY(0x68dadd8)。如何访问数组?感谢您的帮助。再次感谢。 - Perl Gui
@Choroba,我无法解除数组的引用。我已经尝试了${$position}[0]; ${$group{$position}}{"AGE"},但仍然出现错误。我做错了什么? - Perl Gui
显示剩余8条评论

0

根据你已经拥有的代码,你已经接近成功了。假设你打印出来的哈希表叫做%grades,我会这样做:

foreach my $g (sort keys %$grades) {
    print "**$g**\n";
    # put the info to be printed in a temporary hash
    my %temp;
    foreach (@{$grades->{$g}}) {
        push @{$temp{ $_->{GRADE}." ".$_->{POSITION} }}, $_->{NAME};
    }
    foreach (sort keys %temp) {
        # print a count of the number of names, then the grade/position info
        print scalar @{$temp{$_}} . " $_ "
        # @{$temp{$_}} holds the names, so just sort them and print them out.
        . join("\n\t\t\t", sort @{$temp{$_}}) . "\n";
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接