Risposte:
No, non è possibile interrompere un "ciascuno" senza generare un'eccezione. Probabilmente vuoi un loop classico se vuoi che l'interruzione si interrompa in una particolare condizione.
In alternativa, è possibile utilizzare una chiusura "trova" anziché una ciascuno e restituire true quando si sarebbe interrotta.
Questo esempio verrà interrotto prima di elaborare l'intero elenco:
def a = [1, 2, 3, 4, 5, 6, 7]
a.find {
if (it > 5) return true // break
println it // do the stuff that you wanted to before break
return false // keep looping
}
stampe
1
2
3
4
5
ma non stampa 6 o 7.
È anche molto facile scrivere i tuoi metodi iteratori con un comportamento di interruzione personalizzato che accetta le chiusure:
List.metaClass.eachUntilGreaterThanFive = { closure ->
for ( value in delegate ) {
if ( value > 5 ) break
closure(value)
}
}
def a = [1, 2, 3, 4, 5, 6, 7]
a.eachUntilGreaterThanFive {
println it
}
Stampa anche:
1
2
3
4
5
find
meglio di any
- vedi l'altra risposta sotto di @Michal che uno funziona per me
def test = [2] test.findResult{ it * 2 }
restituirà 4 invece di 2
Sostituisci ogni anello con qualsiasi chiusura.
def list = [1, 2, 3, 4, 5]
list.any { element ->
if (element == 2)
return // continue
println element
if (element == 3)
return true // break
}
Produzione
1
3
any()
in questo modo è un po 'fuorviante, ma sicuramente funziona e ti dà la possibilità di rompere o continuare .
No, non puoi uscire da una chiusura in Groovy senza lanciare un'eccezione. Inoltre, non dovresti usare eccezioni per il flusso di controllo.
Se ti ritrovi a voler uscire da una chiusura, dovresti probabilmente prima pensare al motivo per cui vuoi farlo e non a come farlo. La prima cosa da considerare potrebbe essere la sostituzione della chiusura in questione con una delle funzioni (concettuali) di ordine superiore di Groovy. Il seguente esempio:
for ( i in 1..10) { if (i < 5) println i; else return}
diventa
(1..10).each{if (it < 5) println it}
diventa
(1..10).findAll{it < 5}.each{println it}
che aiuta anche la chiarezza. Dichiara l'intento del tuo codice molto meglio.
Il potenziale svantaggio negli esempi mostrati è che l'iterazione si arresta solo all'inizio del primo esempio. Se si considerano le prestazioni, è possibile interromperlo immediatamente.
Tuttavia, per la maggior parte dei casi d'uso che coinvolgono iterazioni di solito è possibile ricorrere a uno dei metodi di ricerca, grep, raccolta, iniezione, ecc. Di Groovy. Di solito prendono un po 'di "configurazione" e poi "sanno" come eseguire l'iterazione per te, in modo che tu possa effettivamente evitare il loop imperativo ovunque possibile.
Usando solo la chiusura speciale
// declare and implement:
def eachWithBreak = { list, Closure c ->
boolean bBreak = false
list.each() { it ->
if (bBreak) return
bBreak = c(it)
}
}
def list = [1,2,3,4,5,6]
eachWithBreak list, { it ->
if (it > 3) return true // break 'eachWithBreak'
println it
return false // next it
}
(1..10) .Ogni {
if (it <5)
stampalo
altro
restituire false
each
, semplicemente non stampa valori maggiori di 4. else
È superfluo, il tuo codice farebbe lo stesso senza di esso. Inoltre, puoi provare a each
non rompere return false
se metti println "not breaking"
subito dopo else
e appena prima return false
.
Potresti rompere RETURN
. Per esempio
def a = [1, 2, 3, 4, 5, 6, 7]
def ret = 0
a.each {def n ->
if (n > 5) {
ret = n
return ret
}
}
Per me funziona!
any
metodo dell'array ritornando false
. Non è possibile interrompere il each
metodo allo stesso modo.