Groovy "각"폐쇄에서 벗어날 수 있습니까?


143

breakGroovy에서 가능 .each{Closure}합니까, 아니면 클래식 루프를 사용해야합니까?

답변:


194

아니요, 예외를 발생시키지 않고 "각"을 중단 할 수는 없습니다. 특정 조건에서 중단을 중단하려면 클래식 루프가 필요할 수 있습니다.

또는 각각 대신 "find"클로저를 사용하고 휴식을 취했을 때 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
}

인쇄물

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    

3
또한 groovy에 패치를 제출하여 클로저에서 null이 아닌 첫 번째 결과를 반환하는 단락 찾기를 수행하는 findResult 메소드를 추가했습니다. 이 방법은 누군가가 각기 일찍 빠져 나가기를 원하는 거의 모든 상황을 다루는 데 사용될 수 있습니다. : 그것은 가능하고 (나는 1.8 바라고 있어요) 그루비로 출시됩니다 있는지 확인하기 위해 패치를 확인 jira.codehaus.org/browse/GROOVY-4253
테드 Naleid

2
나는이 경우를 시도했다 : def a = [1, 2, 3, 4, 5, 6, 7, -1, -2] 1 2 3 4 5 -1 -2를 반환했습니다. 따라서 "breaK"는 작동하지 않습니다.
Phat H. VU

정확한 찾기는 올바른 옵션이며, 각각 반환에 의해 끊어지지 않습니다
Pushkar

입니다 find보다 더 any- 아래에 다른 대답을 참조 @Michal에서 해당 나를 위해 하나 개의 작품
대황

그루비에 대한 테드 날 레이드의 패치는 매우 유용합니다. 요소 자체가 아닌 찾기 작업의 결과가 실제로 필요한 경우 findResult를 대신 사용하십시오. 예 : ​def test = [2] test.findResult{ it * 2 }​2 대신 4를 반환합니다
Doug

57

교체 을 가진 루프 어떤 폐쇄.

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

트릭입니다. "break"이후에 명령문이 있으면 어떻게됩니까? 이 설명은 "break"를 충족 한 후에도 여전히 실행됩니다.
Phat H. VU

2
@ 팻 H. VU 나는 반환을 추가했습니다. "휴식"후 문이 실행되지 않습니다
마이클 Z 무다을

1
답장을 보내 주셔서 감사합니다. 네가 옳아. 나는 또한 당신의 대답에 투표합니다. 더보기 : any 메소드는 DefaultGroovyMethods에 정의되어 있으며 콜렉션의 요소가 제공된 술어 클로저를 충족시키는 경우 true를 리턴하는 술어 함수입니다.
Phat H. VU

any()이 방법으로 사용 하는 것은 약간 오도되지만 확실히 작동하며 중단 하거나 계속할 수있는 기능을 제공합니다 .
vegemite4me 16:15에

1
@ vegemite4me와 같이, 나는 이것이 "간계"라고 생각하지만 당신은 어떤 의미를 잘 이해하지 못합니다. 유지 관리를 위해이 솔루션을 사용하지 않아야합니다.
MatRt

11

아니요, 예외를 발생시키지 않으면 서 Groovy의 폐쇄에서 벗어날 수 없습니다. 또한 제어 흐름에 예외를 사용해서는 안됩니다.

자신이 클로저에서 벗어나기를 원한다면, 아마도 왜 이것을하고 싶은지 아닌 어떻게해야하는지 생각해야합니다. 가장 먼저 고려해야 할 것은 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} 

명확성에 도움이됩니다. 그것은 코드의 의도를 훨씬 더 잘 나타냅니다.

표시된 예제의 잠재적 인 단점은 첫 번째 예제에서 반복 만 중지한다는 것입니다. 성능 고려 사항이있는 경우 즉시 중지하고 싶을 수 있습니다.

그러나 반복이 수반되는 대부분의 유스 케이스의 경우 일반적으로 Groovy의 찾기, grep, 수집, 주입 등의 방법 중 하나를 사용할 수 있습니다. 그들은 일반적으로 "설정"을 한 다음 반복을 수행하는 방법을 "알아"가능하므로 가능한 곳에서는 명령 적 루핑을 실제로 피할 수 있습니다.


1
"아니, 당신은 예외를 throw하지 않고 그루비의 폐쇄에서 분리 할 수 없습니다."이것은 스칼라는 않습니다 볼 것입니다. dev.bizo.com/2010/01/scala-supports-non-local-returns.html
OlliP을

2

특별한 폐쇄 만 사용

// 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
}

3
10 억 개의 행이 있고 첫 번째 호출에서 내부 마감이 true를 반환하면 10 억에서 1을 뺀 값을 반복합니다. :(
sbglasius

-4

(1..10). 각 {

경우 (it <5)

그것을 println

그밖에

거짓을 돌려 주다


2
이것은 each4에서 else벗어나지 않고 단순히 4보다 큰 값을 인쇄하지 않습니다. 불필요합니다. 또한, 증명할 수 each와 휴식하지 않습니다 return false당신이 세우면 println "not breaking"후 바로 else직전 return false.
Stefan van den Akker

가독성을 위해 최소한 코드를 포맷하려면 최소한의 노력을 기울이십시오. 답장하면 시각적으로 미리 볼 수 있으며 사용법은 많이 있습니다.
Mateusz Was

-11

에 의해 중단 될 수 RETURN있습니다. 예를 들어

  def a = [1, 2, 3, 4, 5, 6, 7]
  def ret = 0
  a.each {def n ->
    if (n > 5) {
      ret = n
      return ret
    }
  }

그것은 나를 위해 작동합니다!


6
분명 그가 의미하는 바는 아니지만 OP가 요구 한 것입니다.
Szocske

이것이 부정적인 투표를 한 이유를 설명해 주시겠습니까? 이것은 +133 표로 최고 답변 (설명이 적음)과 동일한 개념으로 보입니다.
Skepi

1
@Skepi 클로저 이상 "중단"할 수 없습니다. any을 반환하여 배열의 메소드를 중단 할 수 있습니다 false. each같은 방법으로 메소드를 중단 할 수 없습니다 .
Nux
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.