Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

foreach only for a section of a list

by dizou (Initiate)
on May 04, 2012 at 14:54 UTC ( #968933=perlquestion: print w/ replies, xml ) Need Help??
dizou has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I am new to perl. I have a list which I want to go through using foreach, except I don't want the loop to include the last entry of the list. Is there a way I can limit the foreach loop to only a section of the list, or in this case, exclude/exit when it reaches the last one?

foreach $core (@somewords) { print " ${core};\n }

so in the example above, if @somewords = a,b,c,d then I only want the foreach loop to print a,b,c. Thanks.

Comment on foreach only for a section of a list
Download Code
Re: foreach only for a section of a list
by kennethk (Monsignor) on May 04, 2012 at 15:01 UTC
    There are a few ways. You can use C-style For Loops:

    for (my $i = 0; $i < @somewords -1; $i++) { print " $somewords[$i];\n" }
    You can use Slices:

    foreach $core (@somewords[0 .. $#somewords-1]) { print " ${core};\n" }
    Or, in some cases, it makes sense to use Loop Control:

    my $i = 0; foreach my $core (@somewords) { next if ++$i == @somewords; print " ${core};\n" }

    TIMTOWTDI

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: foreach only for a section of a list
by Utilitarian (Vicar) on May 04, 2012 at 15:01 UTC
    perl -e '@set=qw(a b c d);for (@set[0..$#set - 1]){print "$_\n";}' a b c
    print "Good ",qw(night morning afternoon evening)[(localtime)[2]/6]," fellow monks."
Re: foreach only for a section of a list
by lune (Monk) on May 04, 2012 at 15:02 UTC
    One possibility is to only iterate over the elements of the array you need, using a slice:
    use strict; my @somewords = ("a", "b", "c"); foreach my $core (@somewords[0..$#somewords-1]) { print "${core};\n"; }
Re: foreach only for a section of a list
by Anonymous Monk on May 04, 2012 at 15:03 UTC
    array slice , range oprator
    for my $ix ( 0 .. ( $#somewords -1 ) ) { print "$somewords[$ix]\n" } for my $chops ( @somewords[ 0 .. ( $#somewords -1 ) ) { print "$chops\n" }
Re: foreach only for a section of a list
by Anonymous Monk on May 04, 2012 at 15:06 UTC

    You could ...

    • store the last element in a variable; compare it on each iteration; if same, exit loop (not good if there are duplicates); or,
    • copy|slice n-1 elements in another array to itierate over; or,
    • better yet, use a counter to keep track of the current (elememt of the) array index, either via explicit C-loop or separately maintained one.
Re: foreach only for a section of a list
by brx (Pilgrim) on May 04, 2012 at 15:19 UTC

    Another way, with pop and push:

    my $last = pop @somewords; foreach my $core (@somewords) { print " $core;\n" } push @somewords,$last;

    Update: it's useless to keep $last. See the improvement by johngg, in reply.

      You could use a do block to scope the existence of $last so that it isn't left lying around.

      knoppix@Microknoppix:~$ perl -Mstrict -wE ' > my @arr = qw{ one two three four }; > push @arr, do { my $last = pop @arr; say for @arr; $last }; > say qq{@arr};' one two three one two three four knoppix@Microknoppix:~$

      Cheers,

      JohnGG

Re: foreach only for a section of a list
by Lotus1 (Chaplain) on May 04, 2012 at 15:20 UTC

    Here are two other ideas: you can store and print the previous value each iteration or you can pop the final element off the array then use foreach on the remaining elements.

    use strict; use warnings; my @somewords = qw(a b c d); my $previous_core = ''; foreach my $core (@somewords) { print "$previous_core\n" if $previous_core ne ''; $previous_core=$core; } print "************\n"; my $popword = pop @somewords; print "popped >${popword}<\n"; print "\@somewords:\n"; print "$_\n" foreach @somewords; print "************\n";
Re: foreach only for a section of a list
by davido (Archbishop) on May 04, 2012 at 15:59 UTC

    I'd be inclined to just iterate over the index:

    foreach my $idx ( 0 .. $#somewords - 1 ) { print " $somewords[$idx]\n"; }

    The slice technique is also nice though:

    foreach my $core ( @somewords[ 0 .. $#somewords - 1 ] ) { print " $core\n"; }

    Dave

Re: foreach only for a section of a list
by johngg (Abbot) on May 04, 2012 at 20:39 UTC

    An interesting selection of approaches in this thread, here's a variation on slicing.

    knoppix@Microknoppix:~$ perl -E ' > @arr = qw{ one two three four }; > say for do { local @arr = @arr[ 0 .. $#arr - 1 ]; @arr }; > say qq{@arr};' one two three one two three four knoppix@Microknoppix:~$

    Update: You can't localise a lexical variable so, if running under strictures you would have to declare @arr with our to make it a package variable or make it a lexical with my and declare a new lexical inside the do block.

    knoppix@Microknoppix:~$ perl -Mstrict -wE ' > our @arr = qw{ one two three four }; > say for do { local @arr = @arr[ 0 .. $#arr - 1 ]; @arr}; > say qq{@arr};' one two three one two three four knoppix@Microknoppix:~$
    knoppix@Microknoppix:~$ perl -Mstrict -wE ' > my @arr = qw{ one two three four }; > say for do { my @arr = @arr[ 0 .. $#arr - 1 ]; @arr}; > say qq{@arr};' one two three one two three four knoppix@Microknoppix:~$

    Cheers,

    JohnGG

      I don't get it. Instead of
          say for do { my @arr = @arr[ 0 .. $#arr - 1 ]; @arr};
      et al, why not just
          say for do { @arr[ 0 .. $#arr-1 ] };
      or (much) better yet...

      >perl -wMstrict -lE "my @arr = qw{ one two three four }; say for @arr[ 0 .. $#arr-1 ]; say qq{@arr}; " one two three one two three four

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://968933]
Approved by kennethk
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2014-09-17 02:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (56 votes), past polls