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

I have the following code snippet:
$u15 = 15; $u105 = 105; $u25 = 25; # for($k=0; $k<=12; $k++) { push @biu_z, $u105 ; } for ($j=0; $j<=26; $j++) { push @biu_yz, [ @biu_z ]; } for ($i=0; $i<=26; $i++) { push @biu, [ @biu_yz ]; } # for($k=0; $k<=12; $k++) { push @zcu_z, $u15 ; } for ($j=0; $j<=26; $j++) { push @zcu_yz, [ @zcu_z ]; } for ($i=0; $i<=25; $i++) { push @zcu, [ @zcu_yz ]; } # # problem ? # for ($k=1; $k<=12; $k++) { # for(my $i=1; $i<=5; $i++) { $biu[$i][4][$k] = $u25; } for(my $i=22; $i<=26; $i++) { $biu[$i][4][$k] = $u25; } for($i=1; $i<=4; $i++) { $biu[$i][23][$k] = $u25; } for($i=23; $i<=26; $i++) { $biu[$i][23][$k] = $u25; } # }
The first part is just creating 3d arrays "biu(i,j,k)" and "ziu(i,j,k)" and setting all the entries to 105 and 15 respectively. If I leave out all the statements after the comment problem ?, it prints out the arrays just as I expected. However, I am trying to change certain array locations to different values, as in the statments following the problem ? statement. It changes all the $i values for $biu in the rows ($j=4 and $j=23) versus just the $i values in the for statements. I believe I am missing something big on the understanding of how arrays work in perl, as I am still thinking in fortran terms. Do I need to make all the $i into my $i ? Thanks in advance

Replies are listed 'Best First'.
Re: Help with multi-dimensional arrays (list of lists)
by wfsp (Abbot) on Nov 26, 2007 at 16:29 UTC
    The first part is just creating 3d arrays "biu(i,j,k)"...
    If I understand you correctly the best way to do that is to construct them the same way you change them later.

    I've used the perlish for loop and started at 0 (you'll need to correct the assignments at the end to match to avoid any off by 1 errors).

    Data::Dumper helps to see what is going on.

    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $u15 = 15; my $u105 = 105; my $u25 = 25; my (@biu); for my $k (0..11) { for my $j (0..25){ for my $i (0..25){ $biu[$k][$j][$i] = $u105; } } } my (@zcu); for my $k (0..11) { for my $j (0..25){ for my $i (0..25){ $zcu[$k][$j][$i] = $u15; } } } for my $k (0..12) { for my $i (0..5) { $biu[$i][4][$k] = $u25; } for my $i (21..25){ $biu[$i][4][$k] = $u25; } for my $i (0..4) { $biu[$i][22][$k] = $u25; } for my $i (21..25) { $biu[$i][22][$k] = $u25; } # } print Dumper \@biu;
Re: Help with multi-dimensional arrays (list of lists)
by ikegami (Patriarch) on Nov 26, 2007 at 16:24 UTC

    [ ] only creates a shallow copy, so while $biu[0], $biu[1], $biu[2], etc contain references to different arrays, all those arrays have the same contents as @biu_yz.

    That means $biu[0][$j], $biu[1][$j], $biu[2][$j], etc all hold the same reference as $biu_yz[$j].

    Fix:

    for my $i (0..12) { for my $j (0..26) { for my $k (0..12) { $biu[$i][$j][$k] = $u105 ; } } }

    By the way, note how much more readable the Perl syntax for counting loops is over the C syntax.

Re: Help with multi-dimensional arrays (list of lists)
by atemon (Chaplain) on Nov 26, 2007 at 16:03 UTC

    Hi,

    in your code,

    push @biu_yz, [ @biu_z ];
    or similar pushes, you are pushing the reference. i.e. the operator [ ] will create an array, with same contents as that of @biu_z and return a reference to the new array. (see Anonymous Arrays)
    When you try to access the value by
    $biu[$i][4][$k] = $u25;
    you need to use '->' operator to derefer it. try
    $biu->[$i][4][$k] = $u25;

    Cheers !

    --VC

    My Home

      Sorry, but that's completely off base.

      The elements of @biu contain references, so you could do

      $biu[$i]->[4]->[$k]

      but -> is optional between indexes, so the following are all fine

      $biu[$i]->[4]->[$k] $biu[$i]->[4][$k] $biu[$i][4]->[$k] $biu[$i][4][$k]

      $biu->[$i][4][$k] dereferences the reference in $biu, but there's no such variable in the program.