Iterating a Foreach loop for dummies...

Discussion in 'Perl Misc' started by Chris L., Jan 18, 2006.

  1. Chris L.

    Chris L. Guest

    Experienced Perl programmer-
    I am running into an issue regarding three Foreach loops- one running
    under another.
    Specifically:
    ---------------------------------------------------------------------------------------------------------------------
    foreach my $entri(@entry){

    foreach my $imm(@imi){

    foreach my $seq(@ses){
    print "$entri $imm $seq\n";
    }
    }
    }
    ------------------------------------------------------------------------------------------------------------------------
    The outcome of this is the first entry in the @entry array, the first
    entry in the @imi array, and then looping these first arrays results
    over and over with the entire @ses array.

    How can I iterate this so the first element of all three arrays are
    printed. Then the second of all three arrays are printed. Then the
    third, etc., etc.
    I have tried using the next, last, redo and LABELS and cannot figure
    this out.
    Thank you for your expertise.
    Chris
     
    Chris L., Jan 18, 2006
    #1
    1. Advertising

  2. Chris L.

    Xicheng Guest

    I am not sure if I understood your question, but if your want to
    parallelly print your three arrays, you may try something like:
    use List::Util qw(max);
    .....
    my $imax=max(@a,@b,@c);
    foreach my $i (0..$imax) {
    print "$a[$i]\t$b[$i]\t$c[$i]";
    }

    Xicheng
    Chris L. wrote:
    > Experienced Perl programmer-
    > I am running into an issue regarding three Foreach loops- one running
    > under another.
    > Specifically:
    > ---------------------------------------------------------------------------------------------------------------------
    > foreach my $entri(@entry){
    >
    > foreach my $imm(@imi){
    >
    > foreach my $seq(@ses){
    > print "$entri $imm $seq\n";
    > }
    > }
    > }
    > ------------------------------------------------------------------------------------------------------------------------
    > The outcome of this is the first entry in the @entry array, the first
    > entry in the @imi array, and then looping these first arrays results
    > over and over with the entire @ses array.
    >
    > How can I iterate this so the first element of all three arrays are
    > printed. Then the second of all three arrays are printed. Then the
    > third, etc., etc.
    > I have tried using the next, last, redo and LABELS and cannot figure
    > this out.
    > Thank you for your expertise.
    > Chris
     
    Xicheng, Jan 18, 2006
    #2
    1. Advertising

  3. Chris L.

    Matt Garrish Guest

    "Chris L." <> wrote in message
    news:...
    > Experienced Perl programmer-
    > I am running into an issue regarding three Foreach loops- one running
    > under another.
    > Specifically:
    > ---------------------------------------------------------------------------------------------------------------------
    > foreach my $entri(@entry){
    >
    > foreach my $imm(@imi){
    >
    > foreach my $seq(@ses){
    > print "$entri $imm $seq\n";
    > }
    > }
    > }
    > ------------------------------------------------------------------------------------------------------------------------
    > The outcome of this is the first entry in the @entry array, the first
    > entry in the @imi array, and then looping these first arrays results
    > over and over with the entire @ses array.
    >
    > How can I iterate this so the first element of all three arrays are
    > printed. Then the second of all three arrays are printed. Then the
    > third, etc., etc.


    It's not pretty, but I suppose you could do something like:

    <untested>

    my $length = length(@entry);
    $length = length(@imi) if length(@imi) > $length;
    $length = length(@ses) if length(@ses) > $length;

    for my $i (0..$length) {
    print $entry[$i] if $entry[$i];
    print $imi[$i] if $imi[$i];
    print $sms[$i] if $sms[$i];
    print "\n";
    }

    You could clean the above up a lot if you know that all the arrays are the
    same length.

    Matt
     
    Matt Garrish, Jan 18, 2006
    #3
  4. Chris L.

    Matt Garrish Guest

    "Matt Garrish" <> wrote in message
    news:lkzzf.7659$...
    >
    > "Chris L." <> wrote in message
    > news:...
    >> Experienced Perl programmer-
    >> I am running into an issue regarding three Foreach loops- one running
    >> under another.
    >> Specifically:
    >> ---------------------------------------------------------------------------------------------------------------------
    >> foreach my $entri(@entry){
    >>
    >> foreach my $imm(@imi){
    >>
    >> foreach my $seq(@ses){
    >> print "$entri $imm $seq\n";
    >> }
    >> }
    >> }
    >> ------------------------------------------------------------------------------------------------------------------------
    >> The outcome of this is the first entry in the @entry array, the first
    >> entry in the @imi array, and then looping these first arrays results
    >> over and over with the entire @ses array.
    >>
    >> How can I iterate this so the first element of all three arrays are
    >> printed. Then the second of all three arrays are printed. Then the
    >> third, etc., etc.

    >
    > It's not pretty, but I suppose you could do something like:
    >
    > <untested>
    >
    > my $length = length(@entry);
    > $length = length(@imi) if length(@imi) > $length;
    > $length = length(@ses) if length(@ses) > $length;
    >
    > for my $i (0..$length) {


    You'd definitely want to lose 1 from that count first, though. See xicheng's
    post for a nicer way to get the max value.

    Matt
     
    Matt Garrish, Jan 18, 2006
    #4
  5. Chris L.

    Matt Garrish Guest

    "Matt Garrish" <> wrote in message
    news:lrzzf.7660$...
    >
    > "Matt Garrish" <> wrote in message
    > news:lkzzf.7659$...
    >>
    >> "Chris L." <> wrote in message
    >> news:...
    >>> Experienced Perl programmer-
    >>> I am running into an issue regarding three Foreach loops- one running
    >>> under another.
    >>> Specifically:
    >>> ---------------------------------------------------------------------------------------------------------------------
    >>> foreach my $entri(@entry){
    >>>
    >>> foreach my $imm(@imi){
    >>>
    >>> foreach my $seq(@ses){
    >>> print "$entri $imm $seq\n";
    >>> }
    >>> }
    >>> }
    >>> ------------------------------------------------------------------------------------------------------------------------
    >>> The outcome of this is the first entry in the @entry array, the first
    >>> entry in the @imi array, and then looping these first arrays results
    >>> over and over with the entire @ses array.
    >>>
    >>> How can I iterate this so the first element of all three arrays are
    >>> printed. Then the second of all three arrays are printed. Then the
    >>> third, etc., etc.

    >>
    >> It's not pretty, but I suppose you could do something like:
    >>
    >> <untested>
    >>
    >> my $length = length(@entry);
    >> $length = length(@imi) if length(@imi) > $length;
    >> $length = length(@ses) if length(@ses) > $length;
    >>


    Ugh! And I just noticed I wrote length instead of scalar! I knew I should
    have tested. Would have saved me the follow-ups...
     
    Matt Garrish, Jan 18, 2006
    #5
  6. Chris L.

    Paul Lalli Guest

    Chris L. wrote:
    > Experienced Perl programmer-
    > I am running into an issue regarding three Foreach loops- one running
    > under another.
    > Specifically:
    > ---------------------------------------------------------------------------------------------------------------------
    > foreach my $entri(@entry){
    >
    > foreach my $imm(@imi){
    >
    > foreach my $seq(@ses){
    > print "$entri $imm $seq\n";
    > }
    > }
    > }
    > ------------------------------------------------------------------------------------------------------------------------
    > The outcome of this is the first entry in the @entry array, the first
    > entry in the @imi array, and then looping these first arrays results
    > over and over with the entire @ses array.
    >
    > How can I iterate this so the first element of all three arrays are
    > printed. Then the second of all three arrays are printed. Then the
    > third, etc., etc.


    #!/usr/bin/perl
    use strict;
    use warnings;
    use List::MoreUtils qw/each_array/;

    my $each = each_array(@entry, @imi, @ses);
    while (my ($entri, $imm, $seq) = $each->()){
    print "$entri, $imm, $seq\n";
    }
    __END__
     
    Paul Lalli, Jan 18, 2006
    #6
  7. Chris L.

    Guest

    Chris L. wrote:
    > How can I iterate this so the first element of all three arrays are
    > printed. Then the second of all three arrays are printed. Then the
    > third, etc., etc.


    You can use the for_each function of the List::MoreUtils module, which
    will let you process as many arrays as you please:

    #!/usr/bin/perl
    use strict;
    use List::MoreUtils qw{each_array};

    my @a = qw{A B C D};
    my @b = qw{a b c d e f g};
    my @c = qw{1 2 3 4 5 6};

    my $each = each_array(@a, @b, @c);
    while ( my ($a, $b, $c) = $each->() ) {
    print "$a, $b, $c\n";
    }

    __END__

    --
    http://DavidFilmer.com
     
    , Jan 18, 2006
    #7
  8. Chris L.

    Anno Siegel Guest

    You would do us all a favor if you put your reply after the question,
    not on top of the whole posting. Interleave it with the quoted text.
    If applicable, trim the quoted text to the parts you are replying to.

    I have rearranged the posting accordingly.

    Xicheng <> wrote in comp.lang.perl.misc:
    > Chris L. wrote:


    > > Experienced Perl programmer-
    > > I am running into an issue regarding three Foreach loops- one running
    > > under another.
    > > Specifically:
    > >

    > -------------------------------------------------------------------------
    > > foreach my $entri(@entry){
    > >
    > > foreach my $imm(@imi){
    > >
    > > foreach my $seq(@ses){
    > > print "$entri $imm $seq\n";
    > > }
    > > }
    > > }
    > >

    > --------------------------------------------------------------------------


    [...]

    > > How can I iterate this so the first element of all three arrays are
    > > printed. Then the second of all three arrays are printed. Then the
    > > third, etc., etc.


    > I am not sure if I understood your question, but if your want to
    > parallelly print your three arrays, you may try something like:
    > use List::Util qw(max);
    > ....
    > my $imax=max(@a,@b,@c);


    This isn't right. It takes the maximum of all list elements from
    @a, @b and @c combined. Since you are running without warnings,
    (yes, I know why) the non-numeric elements get passed over without
    comment. Incidentally the maximum numeric element is 6, which
    happens to be the right answer.

    This is an object lesson on why one should switch off only the warnings
    that need it, in the smallest possible scope.

    Even if max() did take its arguments in scalar context (as you appear
    to have assumed) the index would come out one too high.

    my $imax = max( $#a, $#b, $#c);

    is correct.

    > foreach my $i (0..$imax) {
    > print "$a[$i]\t$b[$i]\t$c[$i]";
    > }


    Here is an alternative that doesn't use indexing:

    my @l = \ ( @a, @b, @c);
    while ( grep @$_, @l ) {
    no warnings 'uninitialized';
    print join( "\t", map shift @$_, @l), "\n";
    }

    That destroys @a, @b and @c. If that's a problem, make that

    my @l = ( [ @a], [ @b], [ @c]);

    If grep() in the loop control is too inefficient,

    for ( 0 .. max( map $#$_, @l) ) {

    can still be used.

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Jan 19, 2006
    #8
  9. Chris L.

    Xicheng Guest

    Anno Siegel wrote:
    > > my $imax=max(@a,@b,@c);

    > This isn't right. It takes the maximum of all list elements from
    > @a, @b and @c combined. Since you are running without warnings,
    > (yes, I know why) the non-numeric elements get passed over without
    > comment. Incidentally the maximum numeric element is 6, which
    > happens to be the right answer.
    > my $imax = max( $#a, $#b, $#c);

    yep, you are right, I tested it on the command line, so did not notice
    the errors. this 'max' function takes a list argument, and thus
    flattens three arrays. Thank you very much for correcting me.. Have a
    good day,
    Xicheng
     
    Xicheng, Jan 19, 2006
    #9
  10. Also sprach :

    > Chris L. wrote:
    >> How can I iterate this so the first element of all three arrays are
    >> printed. Then the second of all three arrays are printed. Then the
    >> third, etc., etc.

    >
    > You can use the for_each function of the List::MoreUtils module, which
    > will let you process as many arrays as you please:


    As a matter of fact it will let you process at most 31 arrays due to the
    way Perl prototypes work.

    Tassilo
    --
    use bigint;
    $n=71423350343770280161397026330337371139054411854220053437565440;
    $m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);
     
    Tassilo v. Parseval, Jan 20, 2006
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kevin Spencer

    Re: foreach loop error

    Kevin Spencer, Aug 22, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    372
    Kevin Spencer
    Aug 22, 2003
  2. Luc Kumps

    Re: foreach loop error

    Luc Kumps, Aug 22, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    393
    Luc Kumps
    Aug 22, 2003
  3. WP
    Replies:
    14
    Views:
    3,557
    Arne Vajhøj
    May 25, 2008
  4. carl
    Replies:
    5
    Views:
    2,499
    James Kanze
    Nov 25, 2009
  5. Isaac Won
    Replies:
    9
    Views:
    445
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page