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

Hi everyone,
I have a few arrays naming @A_1, @A_2, @A_3.... I want to do a loop to for them, e.g.

for(my $i =0; $i<10; $i++)
{ $A_$i[0] = 1234;
........
}

I know $A_$i doesn't work. My question is how can I put $i into the array variable to make the sequence $A_1[0]=1234, $A_2[0]=1234,.......
Thanks
  • Comment on How can increase number sequence in a variable

Replies are listed 'Best First'.
Re: How can increase number sequence in a variable
by haukex (Archbishop) on Nov 17, 2017 at 16:21 UTC

    It's theoretically possible, but "it's stupid to use a variable as a variable name".

    Usually, a hash is what you want, since the keys are strings that you could compose out of other variables. In this case though, it sounds like what you want is an array of arrays. (Update: See also perllol)

    use warnings; use strict; use Data::Dump; my @A; for my $i (0..5) { $A[$i][0] = 1234; } dd @A; __END__ ([1234], [1234], [1234], [1234], [1234], [1234])
Re: How can increase number sequence in a variable
by 1nickt (Canon) on Nov 17, 2017 at 16:34 UTC
      "...pass a reference"

      It depends...

      perl -Mstrict -E 'my @x=(1..2); my @y=(3..4); say join ",", map{$_} (@x,@y)'

      Best regards, Karl

      «The Crux of the Biscuit is the Apostrophe»

      perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

        Hi kgb, I'm not certain what you are intending to show there.

        As I understood it the OP wanted to keep the arrays separated in the loop. And if they are to be contatenated with join, you don't need map.

        perl -Mstrict -E 'my @x=(1..2); my @y=(3..4); say join "->", (@x,@y)' 1->2->3->4


        The way forward always starts with a minimal test.
Re: How can increase number sequence in a variable
by AnomalousMonk (Archbishop) on Nov 17, 2017 at 23:05 UTC

    Just so you'll know what not to do, here's what you asked for in the OP:

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "our @A_0; our @A_1; our @A_2; our @A_3; ;; for my $i (0 .. 3) { my $name = qq{A_$i}; no strict 'refs'; $name->[$i] = 1000 + $i; } dd \@A_0; dd \@A_1; dd \@A_2; dd \@A_3; " [1000] [undef, 1001] [undef, undef, 1002] [undef, undef, undef, 1003]
    This works with strict (and warnings) fully enabled, but only by invoking  no strict 'refs' just before things go sideways. This | Soft referencing only works with package global variables, one of the drawbacks of soft referencing. In the example, our is used to declare the package global arrays. Note that the
        my $name = qq{A_$i};
    statement could be eliminated and the reference could be taken directly from the constructed string:
        qq{A_$i}->[$i] = 1000 + $i;
    (I use Data::Dump::dd() because I like it, but it's not core. Data::Dumper is core.)

    Much better practice is the use of hard references:

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my @A_0; my @A_1; my @A_2; my @A_3; ;; for my $arrayref ( \(@A_0, @A_1, @A_2, @A_3) ) { $arrayref->[0] = 1234; } dd \@A_0; dd \@A_1; dd \@A_2; dd \@A_3; " [1234] [1234] [1234] [1234]
    Note that the variables being operated on are my (or lexical) variables, but the same referencing mechanism works with package globals (our variables) as well. Note also the  \(@ra, @rb, ...) syntax for taking hard references to a collection of (any mixture of) variables. This is just a convenience, and the loop could just as well have been defined
        for my $arrayref (\@A_0, \@A_1, \@A_2, \@A_3) { ... }

    The  \( ... ) device can be used in conjunction with the declaration of a set of variables and the list of references taken can be captured in an array. The set of references in this array can then be operated on as a group. Note that the  \my ( ... ) device can be used only to declare and not to initialize variables. The lexical variables created in the  my (@A_0, @foo, @A_2, @A_3) expression below behave just like any lexical; they could also be our variables.

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my @arrayrefs = ( \my (@A_0, @foo, @A_2, @A_3) ); ;; for my $i (0 .. $#arrayrefs) { $arrayrefs[$i][$i] = 1000 + $i; } dd \@A_0; dd \@foo; dd \@A_2; dd \@A_3; " [1000] [undef, 1001] [undef, undef, 1002] [undef, undef, undef, 1003]
    (Update: The
        my @arrayrefs = ( \my (@A_0, @foo, @A_2, @A_3) );
    statement could be written slightly more simply as
        my @arrayrefs = \my (@A_0, @foo, @A_2, @A_3);
    since the outermost  ( ) grouping is unnecessary.)

    A reference to the  @arrayrefs array could be taken and passed around, etc., etc. Use your imagination — but don't use soft references (without a very good reason, but you didn't hear me say that).

    Update: And here's yet another variation that uses each to simultaneously iterate over the indices and elements of the  @arrayrefs array (needs Perl version 5.12+):

    c:\@Work\Perl>perl -wMstrict -MData::Dump -le "use 5.012; ;; my @arrayrefs = \my (@A_0, @foo, @A_2, @A_3); ;; while (my ($i, $ar) = each @arrayrefs) { $ar->[$i] = 1000 + $i; } dd \@A_0; dd \@foo; dd \@A_2; dd \@A_3; " [1000] [undef, 1001] [undef, undef, 1002] [undef, undef, undef, 1003]


    Give a man a fish:  <%-{-{-{-<

Re: How can increase number sequence in a variable
by AnomalousMonk (Archbishop) on Nov 17, 2017 at 17:06 UTC

    For future reference, what you want to do is to use a "symbolic" or "soft" reference; see perlref. And yes, this is Officially Frowned Upon and yes, you probably want to use a hash or some other "hard" referencing scheme; see also perldsc.


    Give a man a fish:  <%-{-{-{-<