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.