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

Hi all, I have a a problem inside my perl program. Bellow the code:
my $j = 0; my $z = 0; my @results; while ($j <5) { while ( $z < 5) { my @result_1 = `/home/devel/test1.ksh $j`; my @result_2 = `/home/devel/test2.ksh $j`; push @{ $results[$j][$z] }, \@result_1.";"\@result_2; $z++; } $j++; }
My idea was to save inside the array @results the different results of my operations performed during the last while cycle.

The problem is that it seems that for every cycle perl uses the same reference, so in the end in the @results I have only 2 values repeated 5 times.

print @{ $results[0] [0] }[0] = ARRAY00001;ARRAY00002

print @{ $results[0] 1 }[0] = ARRAY00001;ARRAY00002

print @{ $results[0] 2 }[0] = ARRAY00001;ARRAY00002

and so on

How could I solve my problem? What did I do wrong?

Thanks a lot, Pazzeo

Replies are listed 'Best First'.
Re: Question about array reference
by roboticus (Chancellor) on Dec 03, 2011 at 16:49 UTC

    Pazzeo:

    As you observed, it used the same reference each time, so just create a new anonymous array with the data, like this:

    push @{ $results[$j][$z] }, [ @result_1 ], [ @result_2 ];

    Here the square brackets create a new anonymous array, and we fill them with the elements in @result_1 and @result_2.

    Update: Sorry, I misread the code. Please ignore my incorrect reply. chromatic, thanks for pointing out my mistake.

    ...roboticus

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

Re: Question about array reference
by GrandFather (Saint) on Dec 04, 2011 at 03:03 UTC

    Actually you have several problems in your code. Most likely the main issue is that back ticks returns a string so assigning the result to an array is unlikely to be meaningful. With that in mind the value being pushed doesn't make sense. On top of that your while loops should really be for loops to better convey the intent of the loops. So, consider:

    use strict; use warnings; my @results; for my $wibble (0 .. 4) { for my $wobble (0 .. 4) { my $result1 = `/home/devel/test1.ksh $wibble`; my $result2 = `/home/devel/test2.ksh $wibble`; push @{$results[$wibble][$wobble]}, "$result1;$result2"; } }

    Completely untested of course and I'm sure there are better names than wibble and wobble for the two loop counters that convey the sense of what the loops are fore, but I can't guess what they may be.

    True laziness is hard work
Re: Question about array reference
by aaron_baugher (Curate) on Dec 03, 2011 at 19:00 UTC
    push @{ $results[$j][$z] }, \@result_1.";"\@result_2;

    The line above from your code has a syntax error, so it's hard to tell exactly what you're trying to do. Based on the results you're getting, I'd guess your actual code had another . after the second double quote. So it's taking references to the two arrays and concatenating them together as strings with a semi-colon between them, and then pushing them onto the array pointed to by $results[$j][$z]. But treating an array reference like a string returns a value like ARRAY(0x244dd58) corresponding to the memory location of the array, not the contents of the array, which are probably what you want.

    So you could do this a couple different ways. You could put the two arrays together, and save a single reference to the resulting array. Or you could save a reference to an array containing two references to your two arrays, which is probably what you want, assuming you want to be able to tell later where test1.ksh stopped and test2.ksh started.

    The other issue is that push doesn't really make sense here. Your looping with $j and $z guarantees that you're only going to push onto each sub-sub-array once. So that third level of arrays isn't necessary. Just save a reference to your results in $results[$j][$z]. Using the two methods mentioned above:

    #save a reference to a single array containing the lines from both sub +-processes: $results[$j][$z] = [ @result_1, @result_2 ]; print $results[$j][$z][0]; # print the first line of the total output # # or # # save a reference to an array containing references to two arrays eac +h containing the output of one sub-process: $results[$j][$z] = [ \@result_1, \@result_2 ]; print $results[$j][$z][0][0]; #print the first line from test1.ksh print $results[$j][$z][1][0]; #print the first line from test2.ksh

    Aaron B.
    My Woefully Neglected Blog, where I occasionally mention Perl.

      Thank you very much Aaron

      Yes, during the copying in paste I forgot/delete the last . after the ";". I wanted to put the reference of the arrays in one unique array.

      So in the end, your code, did what I want :)

       $results[$j][$z] = [ \@result_1, \@result_2 ];

      Thank you very much

      Pazzeo