2011-11-17 22 views
16

Si tengo un bucle foreach anidado, ¿cómo puedo romper el bucle interno y decirle al exterior que continúe en ese punto sin hacer ningún otro código debajo del bucle interno?Romper el bucle foreach interno y continuar bucle foreach externo

foreach(var item in items) 
{ 
    foreach(var otheritem in otheritems) 
    { 
    if (!double.TryParse(otheritem)) 
    { 
     //break inner loop 
     //continue outer loop so we never get to DoStuff() 
    } 
    } 

    DoStuff(); 
} 
+6

Noto que esa no es la firma de double.TryParse. –

Respuesta

28

¿Y si uso una bandera?

foreach(var item in items) 
{ 
    bool flag = false; 
    foreach(var otheritem in otheritems) 
    { 
    if (!double.TryParse(otheritem)) 
    { 
     flag = true; 
     break; 
    } 
    } 
    if(flag) continue; 

    DoStuff(); 
} 
4

Usted necesita una variable el fin de controlar y que como usted dice .. hacer un break.

bool doStuff = true; 
foreach(var item in items) 
{ 
    doStuff = true; 
    foreach(var otheritem in otheritems) 
    { 
    if (!double.TryParse(otheritem)) 
    { 
     doStuff = false; 
     break; 
    } 
    } 

    if (doStuff) 
     DoStuff(); 
} 
3
foreach(var item in items) 
{ 
    var shouldContinue = false; 

    foreach(var otheritem in otheritems) 
    { 
    if (!double.TryParse(otheritem)) 
    { 
     shouldContinue = true; 
     //break inner loop 
     //continue outer loop so we never get to DoStuff() 
    } 
    } 

    if(shouldContinue) 
    continue; 

    DoStuff(); 
} 
9

simple es mejor ...

bool doStuff = true; 
    foreach(var otheritem in otheritems) 
    { 
    if (!double.TryParse(otheritem)) 
    { 
     doStuff = false; 
     break; 
    } 
    } 
    if(doStuff) DoStuff(); 

Otro enfoque es refactorizar:

foreach(var outerItem in outerLoop) { 
    Foo(outerItem); 
} 
... 
void Foo(OuterItem item) { 
    foreach(var innerItem in innerLoop) { 
     if(someTest) return; 
    } 
    DoStuff(); 
} 

El return asegura la DoStuff no sucede.

0

Iirc a break; la declaración solo romperá el ciclo más cercano, por lo que emitirá un salto; en el bucle interno debería continuar con el siguiente elemento en el bucle externo.

+1

El OP quiere omitir el código restante en el bucle externo y continuar su ejecución en la parte superior del bucle externo. –

0

No está claro desde el fragmento, pero si sólo se tiene que buscar valores no analizable en otheritems continuación, puede utilizar LINQ:

foreach(var item in items) 
{ 
    bool shouldISkip = otheritems.Any(otherItem => !double.TryParse(otherItem)); 
    if(shouldISkip) continue; 
    DoStuff(); 
} 
17
foreach(var item in items) 
{ 
    foreach(var otheritem in otheritems) 
    { 
    if (!double.TryParse(otheritem)) 
    { 
     //... 
     goto nextUpperLoop; 
    } 
    } 

    DoStuff(); 
    nextUpperLoop: ; 
} 
+5

+1 solo por atreverse a usar goto. –

+2

sí, todos intentan evitar usar el goto morbosamente. repugnante ... – BLUEPIXY

+1

Este es probablemente el único uso legítimo de goto. Sin embargo, prefiero la forma de continuar de java etiquetando bucles. – arviman

18

Comienza escribiendo una mejor versión de doble. TryParse:

static double? TryParseDouble(this string s) 
{ 
    double d; 
    return double.TryParse(s, out d) ? (double?)d : (double?)null; 
} 

bien, ahora usted tiene algo que pueda usar para eliminar el bucle interior por completo, por lo que el problema desaparece:

foreach(var item in items) 
    if (!otheritems.Any(otherItem=>otherItem.TryParseDouble() == null)) 
     DoStuff(); 

En lugar de tratar de encontrar la manera de moverse control alrededor, acaba de escribir código que se parece a la lógica. Si la lógica es "no hacer cosas si alguno de los otros elementos no se analiza como dobles", entonces use el predicado Cualquier para probar todos los demás elementos para ver si alguno de ellos no se analiza como dobles. No hay bucles, por lo que no es necesario un control de bucle sofisticado.

Me inclinaría a ir un paso más allá; capture la lógica en una consulta, y luego itere la consulta:

var goodItems = from item in items 
       where !item.OtherItems.Any(otherItem=>otherItem.TryParseDouble() == null)) 
       select item; 

foreach(var goodItem in goodItems) 
    DoStuff(goodItem); 
+1

Un buen consejo, aunque no responde a la pregunta: ¿cómo salir de un bucle interno mientras se continúa con el exterior? En este caso, pudo simplificar el código en un solo bucle, pero puede no ser siempre el caso. – Kokodoko