36

ループ内で break ステートメントを使用する場合のように、クロージャーから戻りたいと思います。

例えば:

largeListOfElements.each{ element->
    if(element == specificElement){
        // do some work          
        return // but this will only leave this iteration and start the next 
    }
}

上記の if ステートメントでは、リストの反復を停止し、不要な反復を避けるためにクロージャーを残したいと考えています。

例外がクロージャー内でスローされ、外部でキャッチされるソリューションを見たことがありますが、そのソリューションはあまり好きではありません。

この種のアルゴリズムを回避するためにコードを変更する以外に、これに対する解決策はありますか?

4

7 に答える 7

5

あなたは間違ったレベルの抽象化に取り組んでいると思います。この.eachブロックはまさに​​その通りに動作します: 各要素に対して 1 回クロージャーを実行します。代わりに、 を使用List.indexOfして適切な を見つけ、specificElementそれに対して必要な作業を行うことをお勧めします。

于 2009-04-19T15:55:10.867 に答える
3

特定の要素が見つかるまですべての要素を処理したい場合は、次のようにすることもできます。

largeListOfElements.find { element ->
    // do some work
    element == specificElement
}

これは、あらゆる種類の「ブレーク条件」で使用できますが。これを使用して、コレクションの最初の n 要素を処理し、

counter++ >= n

閉鎖の終わりに。

于 2009-12-13T14:10:54.450 に答える
1

paulmurray の回答の後、クロージャー内からスローされた例外で何が起こるか確信が持てなかったので、考えやすい JUnit テスト ケースを作成しました。

class TestCaseForThrowingExceptionFromInsideClosure {

    @Test
    void testEearlyReturnViaException() {
        try {
            [ 'a', 'b', 'c', 'd' ].each {                 
                System.out.println(it)
                if (it == 'c') {
                    throw new Exception("Found c")
                } 
            }
        }
        catch (Exception exe) {
            System.out.println(exe.message)
        }
    }
}  

上記の出力は次のとおりです。

a
b
c
Found c

ただし、 「フロー制御に例外を使用しないでください」ということを覚えておいてください。特に、スタック オーバーフローの質問: Why not use exceptions as regular flow of control? を参照してください。

したがって、上記のソリューションは、いずれにしても理想的とは言えません。使用するだけです:

class TestCaseForThrowingExceptionFromInsideClosure {

    @Test
    void testEarlyReturnViaFind() {
        def curSolution
        [ 'a', 'b', 'c', 'd' ].find {                 
            System.out.println(it)
            curSolution = it
            return (it == 'c') // if true is returned, find() stops
        }
        System.out.println("Found ${curSolution}")
    }
}  

上記の出力も次のとおりです。

a
b
c
Found c
于 2013-02-15T22:34:59.363 に答える
1

私がグルーヴィーだと理解しているように、これらの種類のループをショートカットする方法は、ユーザー定義の例外をスローすることです。構文がどうなるかはわかりませんが (grrovy プログラマーではありません)、groovy は JVM 上で実行されるため、次のようになります。

class ThisOne extends Exception {Object foo; ThisOne(Object foo) {this.foo=foo;}}

try { x.each{ if(it.isOk()) throw new ThisOne(it); false} }
catch(ThisOne x) { print x.foo + " is ok"; }     
于 2010-08-13T02:49:54.790 に答える
0

良い oleforループは、ユース ケースの Groovy でも動作します

for (element in largeListOfElements) {
    if(element == specificElement){
        // do some work          
        return
    }
}
于 2021-01-13T11:01:52.890 に答える