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

Hello, I am trying to concatenate a scalar with array name but not sure how to do. Lets say we have two for loops (one nested inside other) like
for ($i = 0; $i <= 5; $i++){ for ($k = 0; $k <=5; $k++){ $array[$k] = $k;} }
I want to create 5 arrays with names like @array1, @array2, @array3 etc. The numeric at end of each array represents value of $i when array creation in progress. Is there a way to do it? Thanks

Replies are listed 'Best First'.
Re: concatenate scalar with array name
by Kenosis (Priest) on Jan 15, 2014 at 05:15 UTC

    Instead of attempting to create variables 'on the fly,' consider creating a hash of arrays (HoA) whose keys are array1 .. array5:

    use strict; use warnings; my %hash; for my $i ( 1 .. 5 ) { for my $k ( 0 .. 4 ) { ${ $hash{ 'array' . $i } }[$k] = $i**$k; } } print "$_: @{ $hash{ $_ } }\n" for sort keys %hash;

    Output:

    array1: 1 1 1 1 1 array2: 1 2 4 8 16 array3: 1 3 9 27 81 array4: 1 4 16 64 256 array5: 1 5 25 125 625

    Hope this helps!

      Not a bad approach. I was thinking only in terms of what he asked, but that would accomplish the same thing. :)

      It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
Re: concatenate scalar with array name
by Eily (Monsignor) on Jan 15, 2014 at 09:57 UTC

    If the arrays have significant differences (they do not have the same meaning, and won't be used the same way), then it's probably better to give them significant names (like "potatoes", "tomatoes", "toes"), in which case a hash can be used (and if the arrays aren't going to be used in the same place, there's no need for having them ordered). Then you can have $hash{potatoes}[0] or $hash{toes}[-1] for exemple.

    If the arrays are equivalent sets, in which case the order may be important, then an array of arrays is probably a clearer solution (and faster, but it's not a significant change if there's little data). This means that instead of $array1[0], $array2[3], $array3[9] you would write $array[1][0], $array[2][3] and $array[3][9]. The difference is that you'll have something at index 0 (it can be undef, in which case your first array will be at 1).

    Since you seem to be in the second case, here is how to do it:

    for my $i (0..4) { for my $j (0..4) { $array[$i][$j] = something($i,$j); } }
    Of course what I said still stands, instead of @array, $i, $j and &something, you should use meaningful names.

    More info in perldsc

Re: concatenate scalar with array name
by Preceptor (Deacon) on Jan 15, 2014 at 09:16 UTC

    As other Monks suggest - it's a bad idea to use variables to define other variable names. There are all sorts of ways that can - and does - go wrong. You lose a lot of ability to check and validate what your program is doing (namespace clashes, figuring out what you called that variable in the first place, later on in the program etc.)

    Hashes basically implement the same functionality - a hash is sort of like an array, but it's 'keyed' via text strings. So when you're trying to use symbolic variable names, then the answer is generally 'just use a hash, that's what they're for'.

    More detail on why it's a bad idea

Re: concatenate scalar with array name
by Laurent_R (Canon) on Jan 15, 2014 at 07:17 UTC
    What you are trying to do is what is called symbolic references (see the documentation on references), and is deprecated and usually frowned upon by most people. The hash of arrays approach suggested above by Kenosis is usually considered to be much better. If you really want to do it the way you said, you'll have to declare your variables with our rather than my and disable some of the strictures with the no strict 'refs'; pragma. But, again, a HoA is certainly a better approach.
Re: concatenate scalar with array name
by boftx (Deacon) on Jan 15, 2014 at 04:29 UTC

    There are at least two ways to do it that I can think of (will have to read the Perl docs to dredge up the details, though.) One involves using eval with a string instead of a block and the other involves mucking with the symbol table. Both will cause some (many?) of the monks to cringe. But, this is Perl, and it allows you do things that are otherwise questionable if you have a good reason to do so.

    In any event, yes, it can be done, and I expect one of the others here with a better memory than mine right now will give you the details on the eval approach as well as why it can be a Bad Idea(tm) use it.

    It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.