Indlejret til hver i Kotlin

1. Introduktion

I denne korte Kotlin-selvstudie ser vi på parameteromfanget inde i a for hver loop's lambda.

Først definerer vi de data, som vi bruger i vores eksempler. For det andet vil vi se, hvordan man bruger for hver at gentage en liste. For det tredje skal vi se på, hvordan man bruger det i indlejrede sløjfer.

2. Testdata

De data, vi bruger, er en liste over lande, der hver indeholder en liste over byer, som igen indeholder en liste over gader:

klasse Land (val navn: String, val byer: Liste) klasse By (val navn: String, val gader: Liste) klasse Verden {val streetsOfAmsterdam = listOf ("Herengracht", "Prinsengracht") val streetsOfBerlin = listOf ("Unter den Linden "," Tiergarten ") val streetsOfMaastricht = listOf (" Grote Gracht "," Vrijthof ") val lande = listOf (Land (" Holland ", listOf (City (" Maastricht ", streetsOfMaastricht), City (" Amsterdam ", streetsOfAmsterdam) ))), Land ("Tyskland", listOf (By ("Berlin", gaderOfBerlin)))} 

3. Enkel for hver

For at udskrive navnet på hvert land på listen kan vi skrive følgende kode:

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

Ovenstående syntaks svarer til Java. Men i Kotlin, hvis lambda kun accepterer en parameter, kan vi bruge det som standardparameternavn og behøver ikke at navngive det eksplicit:

sjovt allCountriesIt () {countries.forEach {println (it.name)}}

Ovenstående svarer også til:

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

Det er værd at bemærke, at vi kun kan bruge det som et implicit parameternavn, hvis der ikke er nogen eksplicit parameter.

For eksempel fungerer følgende ikke:

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

Og vi ser en fejl ved kompileringstidspunktet:

Fejl: (2, 38) Kotlin: Uopklaret reference: det 

4. Indlejret for hver

Hvis vi vil gentage alle lande, byer og gader, kan vi skrive en indlejret løkke:

sjovt allNested () {lande.forEach {println (it.name) it.cities.forEach {println ("$ {it.name}") it.streets.forEach {println ("$ it")}}} 

Her, den første det henviser til et land, det andet det til en by og den tredje det til en gade.

Men hvis vi bruger IntelliJ, ser vi en advarsel:

Den implicitte parameter 'it' for at omslutte lambda skygges

Dette er muligvis ikke et problem, men i linje 6 kan vi ikke længere henvise til landet eller byen. Hvis vi ønsker det, skal vi udtrykkeligt navngive parameteren:

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

5. Alternativer til indlejrede sløjfer

Indlejrede sløjfer er generelt vanskelige at læse og bør om muligt undgås. En mulighed er at bruge flatMap ():

sjov allStreetsFlatMap () {lande.flatMap {it.cities} .flatMap {it.streets} .forEach {println (it)}}

Men hvis vi ikke bruger en indlejret flatMap, vi kan ikke få adgang til by- eller gadenavnet i println udmelding. Hvis vi vil have den samme output som i ovenstående metode allTable () og undgå indlejring, kunne vi tilføje to udvidelsesfunktioner:

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

Og brug derefter disse to metoder med en enkelt flatMap:

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

6. Konklusion

I denne korte artikel så vi, hvordan man bruger standardparameteren det i Kotlin og hvordan man får adgang til parametrene for en ydre for hver indefra en indlejret for hver løkke. Endelig så vi også på, hvordan man undgår indlejrede løkker ved hjælp af flatMap og udvidelsesfunktioner.

Alle kodestykker i denne artikel kan findes i vores GitHub-arkiv.


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