KotlinのNestedforEach
1. 序章
この短いKotlinチュートリアルでは、forEachループのラムダ内のパラメータースコープを見ていきます。
まず、例で使用するデータを定義します。 次に、forEachを使用してリストを反復処理する方法を説明します。 第三に、ネストされたループでそれを使用する方法を見ていきます。
2. テストデータ
使用するデータは国のリストであり、各国には都市のリストが含まれており、都市のリストには通りのリストが含まれています。
class Country(val name : String, val cities : List<City>)
class City(val name : String, val streets : List<String>)
class World {
val streetsOfAmsterdam = listOf("Herengracht", "Prinsengracht")
val streetsOfBerlin = listOf("Unter den Linden","Tiergarten")
val streetsOfMaastricht = listOf("Grote Gracht", "Vrijthof")
val countries = listOf(
Country("Netherlands", listOf(City("Maastricht", streetsOfMaastricht),
City("Amsterdam", streetsOfAmsterdam))),
Country("Germany", listOf(City("Berlin", streetsOfBerlin))))
}
3. シンプルなforEach
リスト内の各国の名前を印刷するには、次のコードを記述できます。
fun allCountriesExplicit() {
countries.forEach { c -> println(c.name) }
}
上記の構文はJavaに似ています。 ただし、Kotlinでは、ラムダが1つのパラメーターのみを受け入れる場合、デフォルトのパラメーター名として it を使用でき、明示的に名前を付ける必要はありません。
fun allCountriesIt() {
countries.forEach { println(it.name) }
}
上記は、次と同等です。
fun allCountriesItExplicit() {
countries.forEach { it -> println(it.name) }
}
it は、明示的なパラメーターがない場合にのみ、暗黙的なパラメーター名として使用できることに注意してください。
たとえば、次は機能しません。
fun allCountriesExplicit() {
countries.forEach { c -> println(it.name) }
}
また、コンパイル時にエラーが発生します。
Error:(2, 38) Kotlin: Unresolved reference: it
4. ネストされたforEach
すべての国、都市、および通りを反復処理する場合は、ネストされたループを作成できます。
fun allNested() {
countries.forEach {
println(it.name)
it.cities.forEach {
println(" ${it.name}")
it.streets.forEach { println(" $it") }
}
}
}
ここで、最初の it は国を指し、2番目の it は都市を指し、3番目のitは通りを指します。
ただし、IntelliJを使用すると、次の警告が表示されます。
Implicit parameter 'it' of enclosing lambda is shadowed
これは問題ではないかもしれませんが、6行目では国や都市を参照できなくなりました。 必要に応じて、パラメーターに明示的に名前を付ける必要があります:
fun allTable() {
countries.forEach { c ->
c.cities.forEach { p ->
p.streets.forEach { println("${c.name} ${p.name} $it") }
}
}
}
5. ネストされたループの代替
ネストされたループは一般に読みにくいため、可能であれば避ける必要があります。 1つのオプションは、 flatMap()を使用することです。
fun allStreetsFlatMap() {
countries.flatMap { it.cities}
.flatMap { it.streets}
.forEach { println(it) }
}
ただし、ネストされた flatMap を使用しない場合、printlnステートメントで都市名または通りの名前にアクセスできません。 上記のメソッドallTable()と同じ出力を取得し、ネストを回避したい場合は、2つの拡張関数を追加できます。
fun City.getStreetsWithCityName() : List<String> {
return streets.map { "$name, $it" }
.toList()
}
fun Country.getCitiesWithCountryName() : List<String> {
return cities.flatMap { it.getStreetsWithCityName() }
.map { "$name, $it" }
}
次に、これら2つのメソッドを単一のflatMapで使用します。
fun allFlatMapTable() {
countries.flatMap { it.getCitiesWithCountryName() }
.forEach { println(it) }
}
6. 結論
この短い記事では、Kotlinでデフォルトパラメーター it を使用する方法と、ネストされたforEachループ内から外部forEachのパラメーターにアクセスする方法を説明しました。 。 最後に、flatMapと拡張関数を使用してネストされたループを回避する方法についても説明しました。
この記事のすべてのコードスニペットは、GitHubリポジトリにあります。