当前位置:  开发笔记 > 编程语言 > 正文

在Kotlin的功能循环中,如何"中断"或"继续"?

如何解决《在Kotlin的功能循环中,如何"中断"或"继续"?》经验,为你挑选了1个好方法。

在科特林,我不能做一个breakcontinue一个功能回路和我的拉姆达内-就像我可以从一个正常的for循环.例如,这不起作用:

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

有旧的文档提到这个可用,但它似乎从未实现过.当我想要continuebreak来自lambda 时,获得相同行为的最佳方法是什么?

注意: 这个问题是由作者故意编写和回答的(自答案问题),因此对于常见问题的Kotlin主题的惯用答案存在于SO中.还要澄清为Kotlin的alphas写的一些非常古老的答案,这些答案对于当前的Kotlin来说是不准确的.



1> Jayson Minar..:

除了您要求提供类似功能之外,还有其他选项.例如:

您可以使用filter以下方法避免处理某些值:( 如acontinue)

dataSet.filter { it % 2 == 0 }.forEach {
    // do work on even numbers
}

您可以使用以下命令停止功能循环takeWhile:( 如abreak)

dataSet.takeWhile { it < 10 }.forEach {
    // do work on numbers as long as they are < 10, otherwise stop
}

一个更复杂的,虽然荒谬的例子,你想要做一些处理,跳过一些结果值,然后停在一组不同的条件,将是:

dataSet.asSequence()
       .takeWhile { it >=  0 }    // a -1 signals end of the dataset (break)
       .map { it + 1 }            // increment each number
       .filterNot { it % 5 == 0 } // skip (continue) numbers divisible by 5
       .map { it - 1 }            // decrement each number by 1
       .filter { it < 100 }       // skip (continue) if number is >= 100
       .drop(5)                   // ignore the first 5 numbers
       .take(10)                  // use the next 10 numbers and end
       .forEach {
           // do work on the final list
       }

这些功能的组合往往不需要continuebreak.这里有无穷无尽的不同选择,而且可以记录下来.为了了解可以做什么,最好是学习Kotlin标准库中可用于集合,延迟序列和可迭代的所有函数.

有时,在某些情况下,您仍然需要变异状态,break或者continue在功能模型中很难做到.你可以使用更复杂的函数来使它工作fold,reduce并与函数结合使用filter,takeWhile但有时候更难以理解.因此,如果您真的想要这种确切的行为,您可以使用lambda表达式返回,该表达式模仿continuebreak取决于您的用法.

这是一个模仿的例子continue:

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

当您遇到嵌套或混乱的情况时,您可以更复杂并使用标签:

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

如果你想做一个break你需要的东西,你可以返回,我们将在这里使用该run()功能来帮助我们:

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

而不是run()它可能是let()apply()任何自然的你周围的forEach那个是你想要打破的地方.但是你也会在同一个块之后跳过代码,forEach所以要小心.

这些是内联函数,所以实际上它们并没有真正增加开销.

阅读所有特殊情况(包括匿名函数)的返回和跳转的Kotlin参考文档.


这是一个单元测试,证明这一切都有效:

@Test fun testSo32540947() {
    val results = arrayListOf>()
    (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()
    run breaker@ {
        (1..20).forEach { x ->
            if (x == 5) return@breaker
            results2.add(x)
        }
    }

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


@Mark我把答案调整为这个功能模型和字面答案的组合.
推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有