Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

Read Every n elements from Array

by vetrivel (Sexton)
on Feb 17, 2011 at 12:13 UTC ( #888698=perlquestion: print w/replies, xml ) Need Help??
vetrivel has asked for the wisdom of the Perl Monks concerning the following question:

Hai ,
How to read every 3 elements from array . I have one way for doing this . Could you tell me any other best way to achieve this .
use Data::Dumper; $test = [ "1" , "2" ,"3" , "4" ,"5" ,"6" ,"7" , "8" ,"9" ,"10" ]; while( @$test ) { @new_Array = splice( @$test , 0 , 3 ) ; print Dumper( \@new_Array ) ; }

Replies are listed 'Best First'.
Re: Read Every n elements from Array
by davido (Archbishop) on Feb 17, 2011 at 12:24 UTC

    I'm interpreting the language of your question to mean read every third element, starting with the first one. That's one situation where a good old "c-style loop" comes in handy:

    use strict; use warnings; use feature qw/say/; my @array = qw/0 1 2 3 4 5 6 7 8 9 10 11 12/; for ( my $idx = 0; $idx < @array; $idx += 3 ) { say $array[$idx]; }

    perlsyn discusses the various loop types. Your splice method is destructive to the original array, and requires that a new array be set up to accommodate the elements you've selected. The method I demonstrated leaves the original array untouched. If you actually want a new array, you could set one up and push the elements into it within the loop.

    Update: You may be asking to read three elements at a time, if I read the language of your question a different way. It's possible to read three elements at a time by just using offsets within the loop, and this would still be non-destructive to your original array.


Re: Read Every n elements from Array
by LanX (Chancellor) on Feb 17, 2011 at 13:23 UTC
    well splice is destructive, you could alternatively use array slices:

    print @arr[$idx..$idx+2]; $idx+=3;


    print @arr[$idx++,$idx++,$idx++];

    Cheers Rolf

      In general, reading and writing to a variable in the same statement can lead to problems. It's not a problem here, but that's not obvious at a glance. For example, that code has undefined behaviour in C. My compiler happens to get it "wrong":

      $ cat a.c #include <stdio.h> int main() { int i = 0; printf("%d %d %d\n", i++, i++, i++); return 0; } $ gcc -Wall -o a a.c && a a.c: In function ‘main’: a.c:5: warning: operation on ‘i’ may be undefined a.c:5: warning: operation on ‘i’ may be undefined 2 1 0

      It's simpler just to avoid the issue.

Re: Read Every n elements from Array
by Eliya (Vicar) on Feb 17, 2011 at 12:28 UTC

    There's nothing wrong with using splice (unless you want the operation to be non-destructive, which you haven't specified).

    Another solution would be List::MoreUtils's natatime.  The example in the docs does more or less exactly the same that your code is doing.

Re: Read Every n elements from Array
by ikegami (Pope) on Feb 17, 2011 at 19:16 UTC

    What kind of improvement are you looking for? That looks like a perfectly fine solution. How could it be any simpler?

    while (@a) { my @group = splice(@a, 0, 3); ... }
    for my $i (0..@a/3-1) { my @group = @a[$i*3..$i*3+2]; ... }
    for (my $i=0; $i<@a; $i+=3) { my @group = @a[$i..$i+2]; ... }
    use List::MoreUtils qw( natatime ); my $i = natatime(3, @a); while (my @group = $it->()) { ... }
Re: Read Every n elements from Array
by hbm (Hermit) on Feb 17, 2011 at 22:00 UTC

    Perhaps shortest?

    $test = [ "1" , "2" ,"3" , "4" ,"5" ,"6" ,"7" , "8" ,"9" ,"10" ]; @new_Array=grep++$i%3<1,@$test;


      That doesn't do the same thing at all. The OP grabs three at a time. That grabs every third.

        What is he trying to do with @new_Array as he is creating new array everytime.

        OP, Do you have any idea what are you trying to achieve here.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://888698]
Approved by ww
[marinersk]: That would mitigate the distraction/jangle issue, but then the information wouldn't be easy to find when it is populated. Plus, I don't currently see a way to move it, but I'm not done poking around on that point yet.
[marinersk]: Ah, you beat me to it.
[LanX]: as long as he has votes left, the nodelet remains
[LanX]: There is a very simple solution ...
[marinersk]: Correct, so one workaround is to leave one vote.
[marinersk]: But I was looking for a more elegant solution. It appears noone online at this time is aware of one.
[LanX]: go to Nodelet Settings and click "All nodelets off"

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (9)
As of 2017-05-29 14:14 GMT
Find Nodes?
    Voting Booth?