Kotlin heeft hele leuke iteratiefuncties, zoals forEach
of repeat
, maar ik kan de break
en continue
operators werken met hen samen (zowel lokaal als niet-lokaal):
repeat(5) {
break
}
(1..5).forEach {
continue@forEach
}
Het doel is om gebruikelijke lussen na te bootsen met de functionele syntaxis zo dicht mogelijk. Het was zeker mogelijk in sommige oudere versies van Kotlin, maar ik heb moeite om de syntaxis te reproduceren.
Het probleem kan een bug zijn met labels (M12), maar ik denk dat het eerste voorbeeld toch zou moeten werken.
Het lijkt me dat ik ergens gelezen heb over een speciale truc/annotatie, maar ik kon geen referentie over het onderwerp vinden. Zou er als volgt uit kunnen zien:
public inline fun repeat(times: Int, @loop body: (Int) -> Unit) {
for (index in 0..times - 1) {
body(index)
}
}
Antwoord 1, autoriteit 100%
Hiermee wordt 1 tot 5 afgedrukt. De return@forEach
werkt als het trefwoord continue
in Java, wat in dit geval betekent dat het nog steeds elke lus uitvoert, maar naar de volgende iteratie als de waarde groter is dan 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)
}
}
Hiermee drukt u 1 tot 10 af, maar slaat 5 over.
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)
}
}
Probeer ze op Kotlin Playground.
Antwoord 2, autoriteit 95%
Bewerken:
Volgens Kotlin’s documentatieis het mogelijk om continue
te simuleren met annotaties.
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")
}
Als u een break
wilt simuleren, voegt u gewoon een run
-blok
toe
fun foo() {
run lit@ {
listOf(1, 2, 3, 4, 5).forEach {
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")
}
}
Oorspronkelijk antwoord:
Aangezien u een (Int) -> Unit
, je kunt er niet uit breken, omdat de compiler niet weet dat het in een lus wordt gebruikt.
Je hebt weinig opties:
Gebruik een normale for-lus:
for (index in 0 until times) {
// your code here
}
Als de lus de laatste code in de methode is
je kunt return
gebruiken om uit de methode te komen (of return value
als het geen unit
methode is).
Gebruik een methode
Maak een aangepaste herhaalmethode die Boolean
retourneert om door te gaan.
public inline fun repeatUntil(times: Int, body: (Int) -> Boolean) {
for (index in 0 until times) {
if (!body(index)) break
}
}
Antwoord 3, autoriteit 39%
Een pauze kan worden bereikt met:
//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")
}
En een continuering kan worden bereikt met:
//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")
}
Zoals iedereen hier aanbeveelt… lees de documenten 😛
https://kotlinlang.org/docs/reference/returns.html# return-at-labels
BEWERKEN:
Hoewel de hoofdvraag over forEach gaat, is het belangrijk om de goede oude “voor” in overweging te nemen. Het gebruik van Kotlin betekent niet dat we forEach altijd moeten gebruiken. Het goede oude “voor” gebruiken is prima, en soms zelfs expressiever en beknopter dan voor elk:
fun foo() {
for(x in listOf(1, 2, 3, 4, 5){
if (x == 3) break //or continue
print(x)
}
print("done with the good old for")
}
Antwoord 4, autoriteit 18%
U kunt return from lambda-expressiegebruiken die een continue
of break
afhankelijk van je gebruik.
Dit wordt behandeld in de gerelateerde vraag: Hoe maak ik een “break” of “continue” in een functionele loop binnen Kotlin?
Antwoord 5, autoriteit 15%
Zoals de Kotlin-documentatie zegt, is het gebruik van return
de weg te gaan. Het goede aan kotlin is dat als je geneste functies hebt, je labels kunt gebruiken om expliciet te schrijven waar je terugkeer vandaan komt:
Functiebereik rendement
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")
}
en
Lokale terugkeer(het stopt niet met doorlopen forEach = vervolg)
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")
}
Bekijk de documentatie, het is echt goed 🙂
Antwoord 6, autoriteit 9%
continue
typ gedrag in 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
}
voor gedrag van het type break
moet je for in until
of for in
gebruiken volgens de lijst is Nullable
of Non-Nullable
-
Voor Nullablelijst:
for (index in 0 until list.size) { val item = list[index] // you can use data item now if () { // your code break } // your code }
-
Voor Non-Nullablelijst:
for (item in list) { // data item will available right away if () { // your code break } // your code }
Antwoord 7, autoriteit 3%
Ik heb hier de perfecte oplossing voor (:
list.apply{ forEach{ item ->
if (willContinue(item)) return@forEach
if (willBreak(item)) return@apply
}}
Antwoord 8
Break-instructie voor geneste lussen forEach():
listOf("a", "b", "c").forEach find@{ i ->
listOf("b", "d").forEach { j ->
if (i == j) return@find
println("i = $i, j = $j")
}
}
Resultaat:
i = a, j = b
i = a, j = d
i = c, j = b
i = c, j = d
Continue statement met anonieme functie:
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
if (value == 3) return
print("$value ")
})
Resultaat:
1 2 4 5
Antwoord 9
fun part2(ops: List<Int>): Int = ops.asSequence()
.scan(0) { acc, v -> acc + v }
.indexOf(-1)
Als je het je kunt veroorloven om van een verzameling een sequence
te maken, zijn de kosten normaal gesproken onbeduidend, dan zou je moeten kunnen profiteren van de uitgestelde functie.
Misschien zie je
asSequence
al in het bovenstaande. Het is hier om ons te redden door de hele lijst door te nemen. Direct nadat we een match hebben viaindexOf
, stopt deze. Bingo! Schrijf ons eenwhile
hier.
zoals in deel 2 van https://medium .com/@windmaomao/kotlin-day-1-up-and-down-38885a5fc2b1
Antwoord 10
misschien verander forEach naar
for(it in myList){
if(condition){
doSomething()
}else{
break //or continue
}
}
het werkt voor hashmaps
for(it in myMap){
val k = it.key
val v = it.value
if(condition){
doSomething()
}else{
break //or continue
}
}