Nestet for hver i Kotlin

1. Introduksjon

I denne korte Kotlin-opplæringen ser vi på parameteromfanget i a for hver loop's lambda.

Først definerer vi dataene vi skal bruke i eksemplene våre. For det andre får vi se hvordan du bruker for hver å gjenta over en liste. For det tredje skal vi se på hvordan du bruker den i nestede løkker.

2. Testdata

Dataene vi bruker er en liste over land, som hver inneholder en liste over byer, som igjen inneholder en liste over gater:

class Country (val name: String, val cities: List) class City (val name: String, val streets: List) class World {val streetsOfAmsterdam = listOf ("Herengracht", "Prinsengracht") val streetsOfBerlin = listOf ("Unter den Linden "," Tiergarten ") val streetsOfMaastricht = listOf (" Grote Gracht "," Vrijthof ") val lands = listOf (Land (" Nederland ", listOf (City (" Maastricht ", streetsOfMaastricht), City (" Amsterdam ", streetsOfAmsterdam) ))), Country ("Germany", listOf (City ("Berlin", streetsOfBerlin)))} 

3. Enkelt for hver

For å skrive ut navnet på hvert land i listen, kan vi skrive følgende kode:

moro allCountriesExplicit () {country.forEach {c -> println (c.name)}} 

Ovennevnte syntaks ligner Java. Men i Kotlin, hvis lambda bare aksepterer en parameter, kan vi bruke den som standardparameternavn og ikke trenger å navngi det eksplisitt:

moro allCountriesIt () {country.forEach {println (it.name)}}

Ovennevnte tilsvarer også:

moro allCountriesItExplicit () {country.forEach {it -> println (it.name)}} 

Det er verdt å merke seg at vi bare kan bruke den som et implisitt parameternavn hvis det ikke er noen eksplisitt parameter.

Følgende fungerer for eksempel ikke:

moro allCountriesExplicit () {country.forEach {c -> println (it.name)}} 

Og vi får se en feil ved kompileringstid:

Feil: (2, 38) Kotlin: Ikke løst referanse: it 

4. Nestet for hver

Hvis vi ønsker å gjenta over alle land, byer og gater, kan vi skrive en nestet løkke:

moro allNested () {country.forEach {println (it.name) it.cities.forEach {println ("$ {it.name}") it.streets.forEach {println ("$ it")}}} 

Her, den første den refererer til et land, det andre den til en by og den tredje den til en gate.

Imidlertid, hvis vi bruker IntelliJ, ser vi en advarsel:

Den implisitte parameteren 'it' for å omslutte lambda skygges

Dette er kanskje ikke noe problem, men i linje 6 kan vi ikke referere til landet eller byen lenger. Hvis vi vil ha det, må vi nevne parameteren eksplisitt:

moro allTable () {country.forEach {c -> c.cities.forEach {p -> p.streets.forEach {println ("$ {c.name} $ {p.name} $ it")}}}} 

5. Alternativer til nestede løkker

Nestede løkker er generelt vanskelige å lese og bør unngås hvis mulig. Et alternativ er å bruke flatMap ():

moro allStreetsFlatMap () {country.flatMap {it.cities} .flatMap {it.streets} .forEach {println (it)}}

Men hvis vi ikke bruker en nestet flatMap, vi får ikke tilgang til by- eller gatenavnet i utskrift uttalelse. Hvis vi vil ha samme utdata som i metoden ovenfor allTable () og unngå hekking, kan vi legge til to utvidelsesfunksjoner:

morsom City.getStreetsWithCityName (): Liste {return streets.map {"$ name, $ it"} .toList ()} fun Country.getCitiesWithCountryName (): Liste {return cities.flatMap {it.getStreetsWithCityName ()} .map { "$ name, $ it"}}

Og bruk deretter disse to metodene med en enkelt flatMap:

moro allFlatMapTable () {country.flatMap {it.getCitiesWithCountryName ()}. forEach {println (it)}}

6. Konklusjon

I denne korte artikkelen så vi hvordan du bruker standardparameteren den i Kotlin og hvordan du får tilgang til parametrene til en ytre for hver innenfra en nestet for hver Løkke. Til slutt så vi også på hvordan man kan unngå nestede løkker flatMap og utvidelsesfunksjoner.

Alle kodebitene i denne artikkelen finner du i GitHub-depotet vårt.


$config[zx-auto] not found$config[zx-overlay] not found