你能打破一个Groovy"每个"关闭?

tin*_*nny 142 groovy

是否可以break从Groovy .each{Closure},或者我应该使用经典循环?

Ted*_*eid 188

不,你不能在没有抛出异常的情况下中止"每个".如果您希望在特定条件下中断,则可能需要经典循环.

或者,您可以使用"查找"闭包而不是每个闭包,并在您休息时返回true.

此示例将在处理整个列表之前中止:

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
}
Run Code Online (Sandbox Code Playgroud)

打印

1
2
3
4
5
Run Code Online (Sandbox Code Playgroud)

但不打印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
}
Run Code Online (Sandbox Code Playgroud)

还打印:

1
2
3
4
5    
Run Code Online (Sandbox Code Playgroud)

  • 我还向groovy提交了一个补丁,它添加了一个findResult方法,该方法执行一个短路查找,返回闭包的第一个非null结果.这种方法可以用来覆盖几乎所有人可能想要在每个早期突破的情况.检查补丁,看它是否被接受并进入groovy(我希望1.8):http://jira.codehaus.org/browse/GROOVY-4253 (3认同)
  • 我已经试过这种情况下:DEF A = [1,2,3,4,5,6,7,-1,-2]它返回1 2 3 4 5 -1 -2.所以,"breaK"不起作用. (2认同)

Mic*_*d a 51

任何盖子替换每个环.

def list = [1, 2, 3, 4, 5]
list.any { element ->
    if (element == 2)
        return // continue

    println element

    if (element == 3)
        return true // break
}
Run Code Online (Sandbox Code Playgroud)

产量

1
3
Run Code Online (Sandbox Code Playgroud)

  • @Phat H. VU我加了回报."休息"之后的声明将不会被执行 (2认同)
  • 感谢您的回复。你说得对。我也投票赞成你的答案。更多:any 方法在 DefaultGroovyMethods 中定义,它是一个谓词函数,如果集合中的元素满足提供的谓词闭包,则返回 true。 (2认同)

Kai*_*nad 10

不,你不能在没有抛出异常的情况下从Groovy中的闭包中断.此外,您不应该使用控制流的异常.

如果你发现自己想要打破封闭,你应该先考虑为什么要这样做而不是如何去做.首先要考虑的是用Groovy(概念)高阶函数之一替换有问题的闭包.以下示例:

for ( i in 1..10) { if (i < 5) println i; else return}
Run Code Online (Sandbox Code Playgroud)

(1..10).each{if (it < 5) println it}
Run Code Online (Sandbox Code Playgroud)

(1..10).findAll{it < 5}.each{println it} 
Run Code Online (Sandbox Code Playgroud)

这也有助于澄清.它更好地说明了代码的意图.

所示示例中的潜在缺点是迭代仅在第一示例中提前停止.如果您有性能方面的考虑因素,可能需要立即停止它.

但是,对于涉及迭代的大多数用例,您通常可以使用Groovy的find,grep,collect,inject等方法.他们通常采取一些"配置"然后"知道"如何为您进行迭代,以便您可以尽可能避免命令性循环.