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

Dear monks,

I have this nested foreach loop

foreach $one (@one) { foreach $two (@two) { $one =~ m/\(.\)(.+)\(.\)/; if ($two eq $1) { push @result, $one; } } }

I need the script to go to the parent foreach loop when $two eq $1, I've tried putting next in the if but it just goes to the next field in the child foreach.

Thanks.

Desmond

Replies are listed 'Best First'.
Re: using next in a nested foreach()
by gryphon (Abbot) on Aug 16, 2005 at 01:36 UTC

    Greetings sandrider,

    In addition to using labels as two other monks have suggested already, you could use last to exit the inner loop, thus nexting to the outer loop.

    foreach my $one (@one) { $one =~ m/\(.\)(.+)\(.\)/; foreach my $two (@two) { if (($1) and ($two eq $1)) { push @result, $one; last; } } }

    TMTOWTDI.

    Update: I moved the m// outside the inner foreach due to japhy's comment. No idea why I didn't see that before. Doh.

    gryphon
    Whitepages.com Development Manager (DSMS)
    code('Perl') || die;

      This solution, of course, doesn't help with existing deeply nested loops. That's where the labels come in really handy. There is the caveat that the misuse of labels can cause very odd behavior (like the sudden termination of you script) if you are not careful (typos).

      Also, to further optimize (typing optimization; not necessarily execution optimization) based on japhy's comment, you could try this instead:

      push @results, grep { grep { $1 eq $_ } @two if ( $_ =~ /\(.\)(.+)\(.\)/ ) } @one;
      You get to use a nested grep, but you check all values of @two and don't stop when you find a match.

      Update: Since grep will localize $_ and I don't need the outer $_ in the inner grep, I optimized away reassigning the outer $_;

      Ivan Heffner
      Sr. Software Engineer, DAS Lead
      WhitePages.com, Inc.
Re: using next in a nested foreach()
by jhourcle (Prior) on Aug 16, 2005 at 01:01 UTC

    Use labels:

    PARENT: foreach $one (@one) { foreach $two (@two) { $one =~ m/\(.\)(.+)\(.\)/; if ($two eq $1) { push @result, $one; next PARENT; } } }

    Odd are, at least three other people will post the exact same thing before I hit 'create'

Re: using next in a nested foreach()
by GrandFather (Saint) on Aug 16, 2005 at 01:07 UTC

    See "Loop Control" in perlsyn


    Perl is Huffman encoded by design.
Re: using next in a nested foreach()
by japhy (Canon) on Aug 16, 2005 at 13:01 UTC
    Nobody mentioned the obvious (to me).

    Move the $one =~ m/.../ line outside of the inner for-loop. There's no reason to do the same thing over and over and over.


    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: using next in a nested foreach()
by sandrider (Acolyte) on Aug 16, 2005 at 03:15 UTC
    Thanks guys for all the help.