2011-11-17 11 views
16

Se ho un ciclo foreach annidato, come posso interrompere il ciclo interno e dire al esterno di continuare in quel punto senza fare altro codice al di sotto del ciclo interno?Interrompe il ciclo foreach interno e continua il ciclo foreach esterno

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

Faccio notare che questo non è la firma di Double.TryParse. –

risposta

28

ne dite di usare una bandiera?

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

Hai bisogno di un variabile per controll che e come dici tu .. fare 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

Semplice è meglio ...

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

Un altro approccio è quello di refactoring:

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

Il return assicura la DoStuff non accade.

0

Iirc a break; l'affermazione interromperà solo il ciclo più vicino, quindi rilascia una pausa; nel ciclo interno dovrebbe continuare con l'elemento successivo sul ciclo esterno.

+1

L'OP vuole saltare il codice rimanente sul ciclo esterno e continuare la sua esecuzione nella parte superiore del ciclo esterno. –

0

non è chiaro dal frammento, ma se hai solo cercare valori non parseable in otheritems quindi è possibile utilizzare 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 per osare usare goto. –

+2

sì, tutti cercano di evitare di usare il goto morbosamente. disgustoso ... – BLUEPIXY

+1

Questo è probabilmente l'unico uso legittimo di goto. Però preferisco il modo in cui java continua a etichettare per loops. – arviman

18

Inizia scrivendo una versione migliore di doppio. TryParse:

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

OK, ora avete qualcosa che si può facilmente utilizzare per eliminare il ciclo interno del tutto, quindi il problema va via:

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

Piuttosto che cercare di capire come spostare il controllo, basta scrivere il codice che assomiglia alla logica. Se la logica è "non fare cose se qualcun altro degli elementi non viene analizzato come doppio", quindi utilizzare il predicato Qualsiasi per testare tutti gli altri elementi per vedere se alcuni di essi non vengono analizzati come doppi. Niente loop, quindi non è necessario alcun controllo del loop di fantasia.

Sarei propenso a fare un ulteriore passo avanti; catturare la logica in una query, e quindi scorrere la query:

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 buon consiglio, anche se non risponde alla domanda: come uscire dal ciclo interno, mentre si continua l'esterno? In questo caso sei stato in grado di semplificare il codice in un singolo ciclo, ma potrebbe non essere sempre così. – Kokodoko