GuiPerl has asked for the wisdom of the Perl Monks concerning the following question:

Hi fellows, I have finally put together a small script that when implemented into a larger context will read data from a flat file and processed from output to Excel using Excel::Writer::XLSX. In the meantime, I am having difficulty accessing the data from the Array of Arrays. I trying to split the colon delimited data, however, the output is incorrect. I have stored each line of data using the $save scalar that concatenates each line from the foreach loop and push the results into an array. The data structure is provided as can be seen. To make a long story short, I would like to access each line of data and each individual data element. Here is the code:
#!C:\Perl64\bin\perl.exe use strict; use warnings; use Data::Dumper; my %AG = ( GAHD => [ { NAME => 'K. Long', POSITION => 'SENIOR OFFICER', GRADE => 'P5', COUNTRY=>'ITALY', PWD=>'Y', DATE_OF_BIRTH=>'4/12/1944', AGE => 45, FEMALE=>'*', VACANT=>'YELLOW' }, { NAME => 'J. Buber', POSITION => 'CHIEF', GRADE => 'D1', COUNTRY=>'ITALY', PWD=>'Y', DATE_OF_BIRTH=>'4/12/1944', AGE => 45, FEMALE=>'*', VACANT=>'YELLOW' }, { NAME => 'M. Amsi', POSITION => 'SENIOR ANIMAL HEALTH OFFICER', GRADE => 'P5', COUNTRY=>'ITALY', PWD=>'Y', DATE_OF_BIRTH=>'4/12/1944', AGE => 45, FEMALE=>'*', VACANT=>'YELLOW' }, { NAME => 'E. Xenu', POSITION => 'SENIOR OFFICER', GRADE => 'P5', COUNTRY=>'ITALY', PWD=>'Y', DATE_OF_BIRTH=>'4/12/1944', AGE => 45, FEMALE=>'*', VACANT=>'YELLOW' }, ], GAGD => [ { NAME => 'P. Cheru', POSITION => 'ANIMAL PRODUCTION OFFICER', GRADE => 'P4', COUNTRY=>'ITALY', PWD=>'Y', DATE_OF_BIRTH=>'4/12/1944', AGE => 45, FEMALE=>'*', VACANT=>'YELLOW' }, { NAME => 'B. Burns', POSITION => 'ANIMAL PRODUCTION OFFICER', GRADE => 'P4', COUNTRY=>'ITALY', PWD=>'Y', DATE_OF_BIRTH=>'4/12/1944', AGE => 45, FEMALE=>'*', VACANT=>'YELLOW' }, { NAME => 'R. Mung', POSITION => 'ANIMAL PRODUCTION OFFICER', GRADE => 'P4', COUNTRY=>'ITALY', PWD=>'Y', DATE_OF_BIRTH=>'4/12/1944', AGE => 45, FEMALE=>'*', VACANT=>'YELLOW' }, { NAME => 'B. Scherf', POSITION => 'ANIMAL PRODUCTION OFFICER', GRADE => 'P4', COUNTRY=>'ITALY', PWD=>'Y', DATE_OF_BIRTH=>'4/12/1944', AGE => 45, FEMALE=>'*', VACANT=>'YELLOW' }, { NAME => 'I. Hoffmann', POSITION => 'CHIEF', GRADE => 'P5', AGE => 45, FEMALE=>'*', VACANT=>'YELLOW', COUNTRY=>'ITALY', PWD=>'Y', DATE_OF_BIRTH=>'4/12/1944', } ]); my %positions; my $counts = 0; my %grades; my $rec; my @new2; my $count=0; my $c; my $save; for my $division (keys %AG) { print "**$division**\n"; my %group; my %group2; for my $person (@{ $AG{$division} }) { my $position = join ':', @{ $person }{qw{GRADE POSITION}}; push @{ $group{$position} },$rec=[$person->{NAME},$person-> +{COUNTRY},$person->{DATE_OF_BIRTH},$person->{AGE},$person->{FEMALE},$ +person->{VACANT},$person->{PWD}] } for my $position ( sort { substr($a, 0, 1) cmp substr($b, 0, 1) || substr($b, 0, 2) cmp substr($a, 0, 2) } keys %grou +p) { $position =~ /(\w\d)\W(.*)/g; my $pos=$1; my $title=$2; my $c=scalar @{ $group{$position} }; $save.=[$c.':'.$pos.':'.$title]; print scalar @{ $group{$position} }.":".$pos.':'.$title. +':'; foreach my $key ( @{ $group{$position} }) { print join ":",$key->[0],$key->[1],$key->[2],$key- +>[3],$key->[4],$key->[5],$key->[6],"\n"; $save.=[':'.$key->[0].':'.$key->[1].':'.$key->[2]. +':'.$key->[3].':'.$key->[4].':'.$key->[5].':'.$key->[6]."\n"]; } } # print Dumper @new2; # exit; push(@new2,$save); } foreach my $l_output (@new2) { my($a,$b,$c,$e,$f,$g,$h,$i) = split (/:/,$l_output); print join " ",$a,$b,$c,$e,$f,$g,$h,$i,"\n"; }
Output from above:
**GAGD** 1:P5:CHIEF:I. Hoffmann:ITALY:4/12/1944:45:*:YELLOW:Y: 4:P4:ANIMAL PRODUCTION OFFICER:P. Cheru:ITALY:4/12/1944:45:*:YELLOW:Y: B. Burns:ITALY:4/12/1944:45:*:YELLOW:Y: R. Mung:ITALY:4/12/1944:45:*:YELLOW:Y: B. Scherf:ITALY:4/12/1944:45:*:YELLOW:Y: **GAHD** 1:D1:CHIEF:J. Buber:ITALY:4/12/1944:45:*:YELLOW:Y: 2:P5:SENIOR OFFICER:K. Long:ITALY:4/12/1944:45:*:YELLOW:Y: E. Xenu:ITALY:4/12/1944:45:*:YELLOW:Y: 1:P5:SENIOR ANIMAL HEALTH OFFICER:M. Amsi:ITALY:4/12/1944:45:*:YELLOW: +Y: ARRAY(0x2f90db8)ARRAY(0x2f90db8)ARRAY(0x2f90e00)ARRAY(0x2f90e00)ARRAY( +0x2f90de8)ARRAY(0x2f90410)ARRAY(0x2f90e00) ARRAY(0x2f90db8)ARRAY(0x2f90db8)ARRAY(0x2f90e00)ARRAY(0x2f90e00)ARRAY( +0x2f90de8)ARRAY(0x2f90410)ARRAY(0x2f90e00)ARRAY(0x2f90cc8)ARRAY(0x2f9 +0cc8)ARRAY(0x2f90cb0)ARRAY(0x2f90cb0)ARRAY(0x2f8edf8)ARRAY(0x2f90cc8) +ARRAY(0x2f90cc8)
Any pointers would be greatly appreciated. In fact, I need to know how to dereference the array.

Replies are listed 'Best First'.
Re: Accessing Array of Arrays
by choroba (Cardinal) on Oct 02, 2014 at 19:45 UTC
    Hasn't this already been solved?
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      I thought so, however, I need to implement further conditions on the arrays. I do not know how to split properly.
        so read the documentation.
Re: Accessing Array of Arrays
by Laurent_R (Canon) on Oct 02, 2014 at 22:44 UTC
    Hi GuiPerl, I haven't read thoroughly through your entire code, but I would suggest that this code:
    for my $division (keys %AG) { # ... for my $person (@{ $AG{$division} }) { # ...
    could possibly be made quite simpler (and also slightly faster, but that probably does not make a measurable difference) with the following syntax:
    for my $division (values %AG) { # ... for my $person (@$division) { # ... }
    The above is untested, but this is a simple demonstration of the same idea under the Perl debugger:
    DB<1> %AG = ( GAHD => [ { name => "foo",}, {name => "bar",} ], GAGD +=> [ { name => "baz",}, {name => "foobar",} ] ); DB<2> x \%AG; 0 HASH(0x6005009f8) 'GAGD' => ARRAY(0x600500680) 0 HASH(0x600500740) 'name' => 'baz' 1 HASH(0x6005006e0) 'name' => 'foobar' 'GAHD' => ARRAY(0x6005007e8) 0 HASH(0x60005f150) 'name' => 'foo' 1 HASH(0x600500848) 'name' => 'bar' DB<3> for $division (values %AG) { for $person (@$division) {print $ +person->{name}, "\n"}}; baz foobar foo bar
    I hope this helps.
Re: Accessing Array of Arrays
by wrog (Friar) on Oct 02, 2014 at 19:42 UTC

    pointer #1: learn to indent

    (i.e., what the hell is going on with lines 133-190? and why all of the random blank lines?)

Re: Accessing Array of Arrays
by pme (Monsignor) on Oct 02, 2014 at 20:13 UTC
    Hi GuiPerl,

    It may help. Just copy this snippet below %AG initialization and run.

    for my $division (sort keys %AG) { print "**$division**\n"; my $cnt = 0; print "nr| NAME | POSITION |GRD|COUNTRY| +PWD|DATE_OF_BIRTH|AGE|FEMALE|VACANT|\n"; for my $person (@{ $AG{$division} }) { printf "%2d|%-12s|%30s|%3s|%7s|%3s|%13s|%3s|%6s|%6s|\n", $cnt, $person->{NAME}, $person->{POSITION}, $person->{GRADE}, $person->{COUNTRY}, $person->{PWD}, $person->{DATE_OF_BIRTH}, $person->{AGE}, $person->{FEMALE}, $person->{VACANT}; $cnt++; } }