Відповіді:
Ні, ви не можете скасувати "кожного", не кидаючи винятку. Ви, ймовірно, хочете класичний шлейф, якщо хочете, щоб перерва припинялася при певних умовах.
Крім того, ви можете використовувати закриття "знайти" замість кожного і повернути істину, коли ви зробили б перерву.
Цей приклад припинить, перш ніж обробити весь список:
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
}
Друкує
1
2
3
4
5
але не друкує 6 або 7.
Крім того, дуже просто написати власні методи ітераторів із власною поведінкою на розрив, яка приймає закриття:
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
}
Також друкує:
1
2
3
4
5
find
краще , ніж any
- см іншу відповідь нижче від @Michal , що один працює для мене
def test = [2] test.findResult{ it * 2 }
повернеться 4 замість 2
Замініть кожну петлю будь-якою застібкою.
def list = [1, 2, 3, 4, 5]
list.any { element ->
if (element == 2)
return // continue
println element
if (element == 3)
return true // break
}
Вихідні дані
1
3
any()
цього способу трохи вводить в оману, але це, безумовно, спрацьовує і дає можливість зламати або продовжувати .
Ні, ви не можете зірватися з закриття в Groovy, не кинувши виняток. Крім того, не слід використовувати винятки для контролю потоку.
Якщо ви виявите, що хочете вирватись із закриття, вам, напевно, слід спочатку подумати, чому ви хочете це зробити, а не як це зробити. Перше, що слід врахувати, може бути заміщенням питання про закриття однією з функцій Гроові (концептуальної) вищого порядку. Наступний приклад:
for ( i in 1..10) { if (i < 5) println i; else return}
стає
(1..10).each{if (it < 5) println it}
стає
(1..10).findAll{it < 5}.each{println it}
що також сприяє ясності. У ньому йдеться про наміри вашого коду набагато краще.
Потенційний недолік показаних прикладів полягає в тому, що ітерація зупиняється лише на початку першого прикладу. Якщо у вас є міркування щодо продуктивності, можливо, ви захочете зупинити його тут і там.
Однак для більшості випадків використання, що стосуються ітерацій, зазвичай можна вдатися до одного з методів пошуку, грепування, збирання, введення тощо. Зазвичай вони приймають певну "конфігурацію", а потім "знають", як зробити ітерацію для вас, щоб ви могли фактично уникнути необхідних циклів, коли це можливо.
Просто за допомогою спеціального закриття
// 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) .each {
якщо (це <5)
println це
ще
повернути хибне
each
, просто не надрукує значення більше 4. Це else
зайве, ваш код зробив би те саме без нього. Крім того, ви можете довести, each
що не порушується, return false
якщо ставити println "not breaking"
відразу після else
і безпосередньо перед цим return false
.
Ви могли пройти повз RETURN
. Наприклад
def a = [1, 2, 3, 4, 5, 6, 7]
def ret = 0
a.each {def n ->
if (n > 5) {
ret = n
return ret
}
}
Це працює для мене!
any
метод масиву, повернувшись false
. Ви не можете порушити each
метод таким же чином.