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

I'm trying to get an array sorted into 3 parts, along the lines of (1,4,7) (2,5,8) (3,6,9). I thought that changing $linkscount = 4 to 0 would be the way to go but that command seems to be being ignored and I get the error message after the first pass. What is going wrong and what is the best way to do this?
foreach (@online) { if ($linkscount == 4) { $linkscount = 0; } $linkscount++; print "$_ :: $linkscount<br>\n"; if ($linkscount == 1) { push @links1, $_; } elsif ($linkscount == 2) { push @links2, $_; } elsif ($linkscount == 3) { push @links3, $_; } else { print "error!"; exit; } }

Replies are listed 'Best First'.
Re: sorting an array
by bart (Canon) on Apr 07, 2007 at 11:35 UTC
    Change
    if ($linkscount == 4) { $linkscount = 0; }
    to
    if ($linkscount == 3) { $linkscount = 0; }
    because you increment the counter after you do this test.

    And your code works in a way that feels very "unperlish" to me, but I'm too lazy to completely rewrite it right now. Perhaps later. For example, there's no need to use 3 independent arrays, use an array of arrays instead, and directly use the counter as an index for what subarray to use.

    push @{$links[$linkscount]}, $_;
    And I'd prefer to let $linkscount go from 0 to 2, instead of from 1 to 3. Because now you'll get an empty slot for index 0. All you have to do is swap the $linkscount++ statement and the above test.
Re: sorting an array
by shmem (Chancellor) on Apr 07, 2007 at 12:13 UTC
    A better way might be
    while (@online) { push @links1, shift @online; push @links2, shift @online; push @links3, shift @online; }

    or as per bart's idea of using an array of anonymous arrays (see perlref)

    while (@online) { push (@{$links[$_]}, shift @online) for 0..2; }
    To access the 2nd element (index 1) in the 3rd sub-array (index 2) you would use
    $var = $links[2]->[1];

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      That's really interesting, thanks very much. I've proved to myself it works by using the following:
      while (@online) { push (@{$links[$_]}, shift @online) for 0..2; } @links1 = @{ $links[0] }; @links2 = @{ $links[1] }; @links3 = @{ $links[2] }; print "@links1<br>@links2<br>@links3";
      I shall try to work with the anonymous arrays going forward rather than the named ones but it does all start to get rather obscure and difficult for a simpleton such as me...
        I remember I had a hard time trying to grok references, creating references and dereferencing. But I got through it, and so will you. And you have to, since references are a crucial concept in perl5.

        Cheers from another simpleton,

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}