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

I have a list of employees and their numbers:
01 Joe 02 Ed 03 Sam 04 Wendy
I have a list of transactions:
yadda 01 abc yadda 03 sss yadda 02 asdsdbc yadda 02 adfgbc yadda 01 abgxvc yadda 02 azdfbc yadda 04 azdfbc yadda 04 abdc
I want to read through my transactions file, and push the 3rd field onto the tail end of the array associated with each employee. I don’t want to:
foreach (@transactions) { #there are dozens of employee numbers… if ($_ eq 01) { push (@joe , $_) ; } if ($_ eq 02) { push (@ed , $_) ; } if ($_ eq 03) { push (@sam , $_) ; } if ($_ eq 04) { push (@sam , $_) ; } if (no others) { push (@unregistered , $_) ; } }
I want to:
foreach (@transactions) { push (@the_correct_employee’s_array_based_on_number , $_) ; }
I want to use all these arrays later to print off different reports. Any help would be appreciated!

Replies are listed 'Best First'.
Re: Using a number to determine which array to push onto
by kennethk (Abbot) on Dec 20, 2010 at 20:14 UTC
    Please see Writeup Formatting Tips for info on how to properly format posts here. In this case, wrap code in <code> tags and paragraphs in <p> tags.

    Use a hash, or more specifically a hash of arrays:

    #! perl use strict; use warnings; use Data::Dumper; my @transactions = ( 'yadda 01 abc', 'yadda 03 sss', 'yadda 02 asdsdbc', 'yadda 02 adfgbc', 'yadda 01 abgxvc', 'yadda 02 azdfbc', 'yadda 04 azdfbc', 'yadda 04 abdc', ); my %results; foreach (@transactions) { my ($number) = /\s(\d+)\s/; push @{$results{$number}}, $_; } print Dumper \%results;

    which outputs:

    $VAR1 = { '01' => [ 'yadda 01 abc', 'yadda 01 abgxvc' ], '03' => [ 'yadda 03 sss' ], '04' => [ 'yadda 04 azdfbc', 'yadda 04 abdc' ], '02' => [ 'yadda 02 asdsdbc', 'yadda 02 adfgbc', 'yadda 02 azdfbc' ] };

    You could also accomplish the above using an array of arrays, relying on the employee number as your index. See perlretut and/or perllol. For a discussion of why to use this structure as opposed to a large number of differently named arrays, see Why it's stupid to use a variable as a variable name.

      No need to stop using employee names.

      use strict; use warnings; use Data::Dumper qw( Dumper ); my %employees = ( '01' => 'Joe', '02' => 'Ed', '03' => 'Sam', '04' => 'Wendy', ); my @transactions = ( 'yadda 01 abc', 'yadda 03 sss', 'yadda 02 asdsdbc', 'yadda 02 adfgbc', 'yadda 01 abgxvc', 'yadda 02 azdfbc', 'yadda 04 azdfbc', 'yadda 04 abdc', ); my %transactions_by_employee; for (@transactions) { my ($employee_number) = /\s(\d+)\s/; my $employee_name = $employees{$employee_number} // 'unregistered'; push @{ $transactions_by_employee{$employee_name} }, $_; } print(Dumper(\%transactions_by_employee));

      That said, it might be advantageous to only resolve the employee numbers during output. This would allow one to differentiate the different unregistered employees, for example.

Re: Using a number to determine which array to push onto
by roboticus (Chancellor) on Dec 20, 2010 at 20:21 UTC

    WearyTraveler:

    Then try an array of arrays, then you can use the number as the array index:

    my @AoA; foreach (@transactions) { #there are dozens of employee numbers… push @{$AoA[$_]}, $_; }

    You can use index 0 for your "unregistered" array, and the natural numbers (1..n) for your arrays. (Note: you used $_ as the value and for the array choice, so I didn't change that in the snippet above. You'll want to have a separate value and index...

    Even better could be a hash of arrays, then you can use something like:

    my %HoA; foreach (@transactions) { my ($name, $num, $value) = ...; $HoA{NAME} = $name; $HoA{NUM} = $num; push @{$HoA{VALS}}, $value; }

    Read perldoc perldsc, perldoc perllol for some hints...

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      
      Thank you for all the help!  I used it and it's helping!