Search code examples
stringperlmultidimensional-array

Perl: Multidimentional arrays and "experimental push" error


I'm a junior perl programmer and have very little experience with multidimentional arrays. I'm not even sure it is the proper data structure for this project.

I have an array of clients that is read in from a file:

my @clientlist = grep(/[A-Z]\w+$/,readdir(DIR));

It produces a list like:

$VAR1 = [
          'AA14A',
          'BB12R',
          'CC34M'
        ];

Each client has some unknown number of elements read from another file that correspond to the client name like:

__U_AA14A_0001, __U_AA14A_0002, __U_AA14A_0003
__U_BB12R_0001, __U_BB12R_0002, __U_BB12R_0003

When I try to assign the corresponding element to the client name:

   my @allclients;
   my $header = $string;
   my $i = 0; # index in array
   foreach my $client (@clientlist) {
        push @allclients{$client}{$i}, $header;
        $i += 1;
   }

it prints:

Useless use of push with no values at ./convert_domains.pl line 97.
Global symbol "%allclients" requires explicit package name (did you forget to declare 
"my %allclients"?) at ./convert_domains.pl line 97.
Experimental push on scalar is now forbidden at ./convert_domains.pl line 97, near "}
{"
syntax error at ./convert_domains.pl line 97, near "}{"

I've also tried numerous variations to the push() function, but they all return some variation of the above.

I'm trying to build something like:

AA14A, __U_AA14A_0001, __U_AA14A_0002, __U_AA14A_0003
BB12R, __U_BB12R_0001, __U_BB12R_0002, __U_BB12R_0003

so I can iterate through it and print out the individual elements.

My main questions are how to properly access a multi-dimentional array of strings. I've also read this perldoc but this doesn't seem to work.

https://perldoc.perl.org/perllol


Solution

  • First of all,

    my @allclients;
    

    should be

    my %allclients;
    

    because you want an associative array (i.e. an array-like structure keyed by strings) and thus a hash.


    Also,

    push @allclients{$client}{$i}, ...;
    

    should be

    $allclients{$client}[$i] = ...;
    

    or

    push @{ $allclients{$client} }, ...;
    

    or

    push $allclients{$client}->@*, ...;
    

    You want to add to the array referenced by $allclients{$client}, so @{ $allclients{$client} } or $allclients{$client}->@*. See Perl Dereferencing Syntax.

    Yes, you never explicitly created any of the multiple arrays and the references to them, but that's not a problem thanks to autovivification.