2010-04-08 12 views
30

Io uso il seguente metodo per interrompere il doppio ciclo in Python.Interrompi il ciclo nidificato (doppio) in Python

for word1 in buf1: 
    find = False 
    for word2 in buf2: 
     ... 
     if res == res1: 
      print "BINGO " + word1 + ":" + word2 
      find = True 
    if find: 
     break 

C'è un modo migliore per interrompere il doppio ciclo?

risposta

36

Probabilmente non è quello che si sta sperando per, ma di solito si vorrebbe avere un break dopo aver impostato find a True

for word1 in buf1: 
    find = False 
    for word2 in buf2: 
     ... 
     if res == res1: 
      print "BINGO " + word1 + ":" + word2 
      find = True 
      break    # <-- break here too 
    if find: 
     break 

un altro modo è quello di utilizzare un generatore di espressione di schiacciare il for in un singolo ciclo

for word1, word2 in ((w1, w2) for w1 in buf1 for w2 in buf2): 
    ... 
    if res == res1: 
     print "BINGO " + word1 + ":" + word2 
     break 

Si può anche considerare l'utilizzo di itertools.product

from itertools import product 
for word1, word2 in product(buf1, buf2): 
    ... 
    if res == res1: 
     print "BINGO " + word1 + ":" + word2 
     break 
+1

+1 semplice ma elegante! –

+0

itertools.product() è un ottimo approccio. –

+0

Oggi ho imparato qualcosa :) – wonzbak

5

Refactor utilizzando le funzioni in modo da poter tornare quando si trova il "bingo".

La proposta di consentire rottura esplicita di cicli annidati è stata respinta: http://www.python.org/dev/peps/pep-3136/

+1

Questo dovrebbe essere il top votato risposta IMO. –

9

maggior parte delle volte è possibile utilizzare una serie di metodi per rendere un singolo ciclo che fa la stessa cosa come un doppio anello.

Nel tuo esempio, è possibile utilizzare itertools.product per sostituire lo snippet di codice con

import itertools 
for word1, word2 in itertools.product(buf1, buf2): 
    if word1 == word2: 
     print "BINGO " + word1 + ":" + word2 
     break 

Le altre funzioni itertools sono buoni per altri modelli troppo.

+0

Penso che tu intenda "itertools.product". 'combination' produce tuple di lunghezza n da una singola sequenza – Jimmy

+0

Penso che tu intenda' itertools.product' –

+0

oh bah .... Sono un idiota stasera. – magcius

29

Il metodo consigliato in Python per la rottura cicli annidati è ... Eccezione

class Found(Exception): pass 
try: 
    for i in range(100): 
     for j in range(1000): 
      for k in range(10000): 
       if i + j + k == 777: 
        raise Found 
except Found: 
    print i, j, k 
+2

Davvero? Non ho mai visto eccezioni raccomandate per nulla tranne, beh, cose eccezionali. – dave

+10

In realtà, Python ha un approccio un po 'diverso rispetto alle eccezioni e questo uso è OK. – Guard

+0

Mi piace questa idea perché copre anche le situazioni in cui è necessario iterare su un elenco bidimensionale con cicli nidificati. Alcune altre idee non funzionano per questo perché il ciclo annidato utilizza la variabile fornita dal genitore per il ciclo per ottenere più di un elemento su cui eseguire l'iterazione. – Shule

Problemi correlati