Kotlin有非常好的迭代函数,例如forEach
或repeat
,但我无法让break
和continue
运算符与它们一起工作(本地和非本地):
repeat(5) {
break
}
(1..5).forEach {
continue@forEach
}
目标是模拟通常的循环,其功能语法尽可能接近。在某些旧版本的Kotlin中肯定是可能的,但我很难重现语法。
问题可能是标签错误(M12),但我认为第一个例子应该可行。
在我看来,我已经在某个地方读过关于特殊技巧/注释的内容,但我找不到关于这个主题的任何参考。可能如下所示:
public inline fun repeat(times: Int, @loop body: (Int) -> Unit) {
for (index in 0..times - 1) {
body(index)
}
}
答案 0 :(得分:61)
这将打印1到5. return@forEach
的行为类似于Java中的关键字continue
,这意味着在这种情况下,它仍然会执行每个循环,但如果值更大,它会跳到下一次迭代比5。
fun main(args: Array<String>) {
val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
nums.forEach {
if (it > 5) return@forEach
println(it)
}
}
这将打印1到10但跳过5。
fun main(args: Array<String>) {
val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
nums.forEach {
if (it == 5) return@forEach
println(it)
}
}
在Kotlin Playground处尝试。
答案 1 :(得分:27)
修改强>:
根据Kotlin的old documents - link is broken,应该可以使用注释。但是,它还没有实现。
未实现自定义控件结构的中断和继续 但
此功能的issue为3年,所以我想它不会被修复。
原始答案:
由于您提供了(Int) -> Unit
,因此您无法从中断,因为编译器不知道它是在循环中使用的。
你几乎没有选择:
使用常规for循环:
for (index in 0..times - 1) {
// your code here
}
如果循环是方法中的最后一个代码
您可以使用return
退出该方法(如果不是return value
方法,则使用unit
。)
使用方法
创建一个自定义重复方法方法,返回Boolean
以继续。
public inline fun repeatUntil(times: Int, body: (Int) -> Boolean) {
for (index in 0..times - 1) {
if (!body(index)) break
}
}
答案 2 :(得分:25)
您可以使用模仿continue
或break
的{{3}},具体取决于您的使用情况。
相关问题涉及此问题:return from lambda expression
答案 3 :(得分:10)
作为Kotlin documentation says,使用return
是可行的方法。关于kotlin的好处是,如果您具有嵌套函数,则可以使用标签来显式地写出返回的来源:
功能范围返回
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return // non-local return directly to the caller of foo()
print(it)
}
println("this point is unreachable")
}
和 本地返回(不会停止forEach =连续)
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit // local return to the caller of the lambda, i.e. the forEach loop
print(it)
}
print(" done with explicit label")
}
查看文档,真的很好:)
答案 4 :(得分:9)
可以使用以下方法实现突破:
//Will produce"12 done with nested loop"
//Using "run" and a tag will prevent the loop from running again. Using return@forEach if I>=3 may look simpler, but it will keep running the loop and checking if i>=3 for values >=3 which is a waste of time.
fun foo() {
run loop@{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop // non-local return from the lambda passed to run
print(it)
}
}
print(" done with nested loop")
}
并且可以通过以下方式实现继续:
//Will produce: "1245 done with implicit label"
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // local return to the caller of the lambda, i.e. the forEach loop
print(it)
}
print(" done with implicit label")
}
正如这里的任何人所建议的...阅读文档:P https://kotlinlang.org/docs/reference/returns.html#return-at-labels
答案 5 :(得分:6)
continue
在forEach
中的行为
list.forEach { item -> // here forEach give you data item and you can use it
if () {
// your code
return@forEach // Same as continue
}
// your code
}
对于break
类型的行为,您必须使用for until
for (index in 0 until list.size) {
val item = list[index] // you can use data item now
if () {
// your code
break
}
// your code
}
答案 6 :(得分:2)
forEach()的嵌套循环的中断语句:
listOf("a", "b", "c").forEach find@{ i ->
listOf("b", "d").forEach { j ->
if (i == j) return@find
println("i = $i, j = $j")
}
}
结果:
i = a, j = b
i = a, j = d
i = c, j = b
i = c, j = d
具有匿名功能的继续语句:
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
if (value == 3) return
print("$value ")
})
结果:
1 2 4 5
答案 7 :(得分:0)
可能将每个更改为
for(it in myList){
if(condition){
doSomething()
}else{
break //or continue
}
}
它适用于哈希图
for(it in myMap){
val k = it.key
val v = it.value
if(condition){
doSomething()
}else{
break //or continue
}
}
答案 8 :(得分:0)
fun part2(ops: List<Int>): Int = ops.asSequence()
.scan(0) { acc, v -> acc + v }
.indexOf(-1)
如果您有能力将一个收藏集转换为sequence
,通常成本是微不足道的,那么您应该能够利用延期功能。
您可能已经注意到上面的
asSequence
。这里是为了节省我们遍历整个列表的时间。通过indexOf
进行比赛后,比赛将立即停止。答对了!救我们,在这里写一个while
。
如https://medium.com/@windmaomao/kotlin-day-1-up-and-down-38885a5fc2b1的第2部分
答案 9 :(得分:0)
我对此有一个完美的解决方案(:
list.apply{ forEach{ item ->
if (needsToContinue(item)) return@forEach
if (needsToBreak(item)) return@apply
}}