我如何做一个“休息”或“继续”当在Kotlin中的功能循环中? [英] How do I do a "break" or "continue" when in a functional loop within Kotlin?

查看:197
本文介绍了我如何做一个“休息”或“继续”当在Kotlin中的功能循环中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Kotlin中,我不能在函数循环和我的lambda中执行 break continue - 就像我一样可以从正常循环。例如,这是行不通的:

 (1..5).forEach {
continue @ forEach //不允许,也不允许break @ forEach
}

旧文档,它提到了这一点,但它出现了它从未实现。当我希望从lambda内继续或 break 时获得相同行为的最佳方式是什么?



注意: 这个问题是由作者故意编写和回答的(自我回答的问题),以便在SO中提供对常见问题Kotlin主题的习惯性答案。此外,还要澄清一些针对Kotlin的alpha版本编写的真正旧的答案,这些答案对于当今的Kotlin来说是不准确的。 解决方案

您可以使用模仿<$的从lambda表达式返回 c $ c> continue 或 break 取决于您的使用情况。



这是一个一个模仿继续的例子:

  (1..5).forEach {
if(it == 3)return @ forEach // mimic continue @ forEach
// ...做更多的事
}

当您遇到嵌套或令人困惑的情况时,您可以更加复杂并使用标签:

 (1..3).forEach outer @ {x  - > 
(1..3).forEach inner @ {y - >
if(x == 2&& y == 2)return @ outer // mimic continue @ outer
if(x == 1&& y == == 1)return @ inner // mimic continue @ inner
// ...做更多的事
}
}

如果你想做一个 break ,你需要一些你可以返回的循环之外的东西,在这里我们将使用 run()函数来帮助我们:

  run breaker @ {
(1。 .20).forEach {x - >
if(x == 5)return @ breaker // mimic break @ forEach
// ...做更多的事
}
}

而不是 run()它可以是 let ) apply()或者任何你自己围绕 forEach 你想摆脱。但是你也会跳过 forEach 之后的代码块,所以要小心。



这些是内联函数所以他们真的不会真正增加开销。



阅读Kotlin参考文档返回并跳转所有特殊情况,包括匿名函数。 $ b




这是一个单元测试,证明了这一切:

  @Test fun testSo32540947(){
val results = arrayListOf< Pair< Int,Int>>()
(1..3).forEach outer @ {x - >
(1..3).forEach inner @ {y - >
if(x == 2&& y == 2)return @ outer // continue @outer
if(x == 1&& y == 1)return @ inner / / continue @inner
results.add(Pair(x,y))
}
}

assertEquals(listOf(Pair(1,2),Pair 1,3),Pair(2,1),Pair(3,1),Pair(3,2),Pair(3,3)),结果)
$ b $ val result2 = arrayListOf< Int> ;()
run breaker @ {
(1..20).forEach {x - >
if(x == 5)return @ breaker
results2.add(x)
}
}

assertEquals(listOf(1,2, 3,4),results2)
}


In Kotlin, I cannot do a break or continue within a function loop and my lambda -- like I can from a normal for loop. For example, this does not work:

(1..5).forEach {
    continue@forEach  // not allowed, nor break@forEach
}

There are old documentation that mentions this being available but it appears it was never implemented. What is the best way to get the same behavior when I want to continue or break from within the lambda?

Note: this question is intentionally written and answered by the author (Self-Answered Questions), so that the idiomatic answers to commonly asked Kotlin topics are present in SO. Also to clarify some really old answers written for alphas of Kotlin that are not accurate for current-day Kotlin.

解决方案

You can use return from lambda expression which mimics a continue or break depending on your usage.

Here is a an example mimicking continue:

(1..5).forEach  {
    if (it == 3) return@forEach  // mimic continue@forEach
    // ... do something more
}

And you can go more complicated and use labels when you having nesting or confusing situations:

(1..3).forEach outer@ { x ->
    (1..3).forEach inner@ { y ->
        if (x == 2 && y == 2) return@outer // mimic continue@outer
        if (x == 1 && y == 1) return@inner // mimic continue@inner
        // ... do something more
    }
}

If you want to do a break you need something outside the loop that you can return from, here we will use the run() function to help us:

run breaker@ {
    (1..20).forEach { x ->
        if (x == 5) return@breaker  // mimic break@forEach
        // ... do something more
    }
}

Instead of run() it could be let() or apply() or anything naturally you have surrounding the forEach that is a place you want to break from. But you will also skip the code within the same block following the forEach so be careful.

These are inlined functions so really they do not really add overhead.

Read the Kotlin reference docs for Returns and Jumps for all the special cases including for anonymous functions.


Here is a unit test proving this all works:

@Test fun testSo32540947() {
    val results = arrayListOf<Pair<Int,Int>>()
    (1..3).forEach outer@ { x ->
        (1..3).forEach inner@ { y ->
            if (x == 2 && y == 2) return@outer // continue @outer
            if (x == 1 && y == 1) return@inner // continue @inner
            results.add(Pair(x,y))
        }
    }

    assertEquals(listOf(Pair(1,2), Pair(1,3), Pair(2,1), Pair(3,1), Pair(3,2), Pair(3,3)), results)

    val results2 = arrayListOf<Int>()
    run breaker@ {
        (1..20).forEach { x ->
            if (x == 5) return@breaker
            results2.add(x)
        }
    }

    assertEquals(listOf(1,2,3,4), results2)
}

这篇关于我如何做一个“休息”或“继续”当在Kotlin中的功能循环中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆