Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
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 (Abbot) 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 imbibing at the Monastery: (7)
As of 2015-07-06 07:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (70 votes), past polls