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

Is there a better way to select every third element of an array? This works but it is clunky!
TIA
jg
#!/usr/local/bin/perl -w use strict; my @a=qw(las vegas every saturday night third is my element); my $leng= @a; my $i; print "the index of the array is $leng. \n"; for ($i=0; $i <= $leng; $i++) { if (($i+1)%3==0) { print "$a[$i] "; } }
Ain't no time to hate! Barely time to wait! ~RH

Replies are listed 'Best First'.
Re: Elegantly Selecting Every 3rd Element in an Array.
by Masem (Monsignor) on Sep 29, 2001 at 02:03 UTC
    my $count = 0; my @every_3rd = grep { ( ++$count % 3 == 0 ) } @array;

    -----------------------------------------------------
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
    It's not what you know, but knowing how to find it if you don't know that's important

      Without the extra variable declaration:
      my @every_3rd = @array[grep { ! (($_+1) % 3) } 0..$#array];

      Update: Fixed (due to jerrygarciuh's catch). Nothing like untested code. And precedence. (though looking at the precedence table in perlop, it looks like what I had (in jerry's node below) should've worked. Bug? Can someone explain?).

      Another update:tye explains below. Though I think precedence of parens should differ between 'functions' and 'operators'. Oh well...

        Runrig,
        Well, maybe I botched it, but all I did was change @array to my var @a like so:
        my @a=qw(las vegas every saturday night third is my element); my @every_3rd = @a[grep { not ($_+1) % 3 } 0..$#a]; print "@every_3rd";
        and tell it to print and it runs without error but prints nothing.
        ???
        jg

        Ain't no time to hate! Barely time to wait! ~RH
Re: Elegantly Selecting Every 3rd Element in an Array.
by blakem (Monsignor) on Sep 29, 2001 at 02:01 UTC
    Both of these work:
    print "$a[$_*3+2] " for (0..$#a/3); print join ' ', @a[map {$_*3+2} (0..$#a/3)];

    Update: Actually if @a has 3N+2 elements, the above two lines will attempt to grab an extra element from beyond the end of the list.... here are the fixed versions:

    print "$a[$_*3-1] " for (1..@a/3); print "\n"; print join ' ', @a[map {$_*3-1} (1..@a/3)]; print "\n";

    -Blake

Re: Elegantly Selecting Every 3rd Element in an Array.
by stefp (Vicar) on Sep 29, 2001 at 02:04 UTC
    local $,=' '; my $i=0; my @a=qw(las vegas every saturday night third is my element); print grep { ! (++$i %3) } @a;

    prints "every third element";

    -- stefp

Re: Elegantly Selecting Every 3rd Element in an Array.
by converter (Priest) on Sep 29, 2001 at 02:10 UTC

    Give this a try:

    for ($i=0; $i < @a; $i += 3) { print "$a[$i] "; }

    conv

      Maybe I did something wrong, but when I run your example I get "las saturday is" and not "every third element".

      "Make everything as simple as possible, but not simpler." -- Albert Einstein

        I noticed that too.... easy fix though, replace $i=0 with $i=2. As written, the code gives you every third word, but it doesn't start on the "correct" one.

        -Blake

Re: Elegantly Selecting Every 3rd Element in an Array.
by demerphq (Chancellor) on Sep 30, 2001 at 20:55 UTC
    Well, I realize that this has been answered to death, but heres a solution along a very different line, which also offers some extra flexibility.

    #!/usr/local/bin/perl -w use strict; use Tie::Cycle; $\=$/; my @a=qw(want vegas every first night third array my element); tie my $ok,'Tie::Cycle',[0,0,1]; $ok && print $_ foreach @a;
    The flexibility of this approach can be seen by changing [0,0,1] to [1,0,1].

    Of course I'm not really sure why anyone would _want_ to do anything like this, but you never know what'll come up...

    :-)

    Yves
    --
    You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)