リスト — zip() / unzip()
| 対応: | Kotlin 1.0(2016) |
|---|
Kotlinの『zip()』は2つのリストを要素ごとにペアにしたリストを返します。『unzip()』はペアのリストを2つのリストに分解します。リストの並列処理や、複数のデータ列を結合する場合に使います。
構文
val names = listOf("八神庵", "草薙京", "テリー・ボガード")
val scores = listOf(85, 72, 91)
// zip — 対応する要素を Pair にします。
val zipped = names.zip(scores)
// [Pair("八神庵", 85), Pair("草薙京", 72), Pair("テリー・ボガード", 91)]
// zip with transform — カスタム変換します。
val results = names.zip(scores) { name, score -> "$name: $score点" }
// unzip — Pair のリストを2つのリストに分解します。
val (n, s) = zipped.unzip() // names, scores に戻ります。
メソッド一覧
| メソッド | 概要 |
|---|---|
| リストA.zip(リストB) | 2つのリストを Pair のリストに結合します。短い方の長さに合わせます。 |
| リストA.zip(リストB) { a, b -> 変換 } | 変換ラムダを指定して zip します。 |
| ペアリスト.unzip() | Pair<A, B> のリストを Pair<List<A>, List<B>> に分解します。 |
| リスト.zipWithNext() | 隣り合う要素のペアのリストを返します(差分計算などに使います)。 |
| リスト.zipWithNext { a, b -> } | 隣り合う要素を変換してリストを返します。 |
サンプルコード
sample_list_zip_unzip.kt
fun main() {
// 基本の zip
val names = listOf("八神庵", "草薙京", "テリー・ボガード", "ブルー・マリー")
val scores = listOf(85, 72, 91, 68)
val ages = listOf(20, 20, 24) // 短い方に合わせます(3件)
val songs = listOf("嵐のサキソフォン2", "ESAKA", "Kurikinton", "Blue Mary's Blues")
val zipped = names.zip(scores)
println("zip: $zipped")
// zip with transform(変換付き)
val results = names.zip(scores) { name, score ->
"$name: ${score}点 (${if (score >= 80) "合格" else "不合格"})"
}
results.forEach { println(it) }
println()
// 長さが異なる場合(短い方に合わせます)
val nameAge = names.zip(ages)
println("長さ違い zip: $nameAge") // 3件
println()
// 名前と曲の zip
val nameSongPairs = names.zip(songs) { name, song -> "$name → $song" }
nameSongPairs.forEach { println(it) }
println()
// unzip — Pair を2つのリストに分解します。
val (nameList, scoreList) = zipped.unzip()
println("名前: $nameList")
println("点数: $scoreList")
println()
// zipWithNext — 隣接要素のペアを作ります(差分計算)
val temps = listOf(20.0, 22.5, 19.0, 25.0, 23.0)
println("気温変化:")
temps.zipWithNext { today, tomorrow ->
val diff = tomorrow - today
val dir = if (diff > 0) "↑" else if (diff < 0) "↓" else "→"
println(" ${today}℃ $dir ${tomorrow}℃ (${"%.1f".format(diff)})")
}
println()
// 3つのリストを zip(2回のzipで対応)
val first = listOf(1, 2, 3)
val second = listOf("a", "b", "c")
val third = listOf(true, false, true)
val triple = first.zip(second).zip(third) { (a, b), c -> Triple(a, b, c) }
triple.forEach { println(it) }
}
kotlinc list_zip_unzip.kt -include-runtime -d list_zip_unzip.jar java -jar list_zip_unzip.jar zip: [(八神庵, 85), (草薙京, 72), (テリー・ボガード, 91), (ブルー・マリー, 68)] 八神庵: 85点 (合格) 草薙京: 72点 (不合格) テリー・ボガード: 91点 (合格) ブルー・マリー: 68点 (不合格) 長さ違い zip: [(八神庵, 20), (草薙京, 20), (テリー・ボガード, 24)] 八神庵 → 嵐のサキソフォン2 草薙京 → ESAKA テリー・ボガード → Kurikinton ブルー・マリー → Blue Mary's Blues 名前: [八神庵, 草薙京, テリー・ボガード, ブルー・マリー] 点数: [85, 72, 91, 68] 気温変化: 20.0℃ ↑ 22.5℃ (2.5) 22.5℃ ↓ 19.0℃ (-3.5) 19.0℃ ↑ 25.0℃ (6.0) 25.0℃ ↓ 23.0℃ (-2.0) (1, a, true) (2, b, false) (3, c, true)
概要
『zip()』は2つのリストを対応させて処理するときに便利です。長さが異なる場合は短い方に合わせて切り捨てられます(例外は発生しません)。
『zipWithNext()』は連続する2要素の差分や変化率を計算するときに使います。for ループで添字を使う処理の代わりになります。
リストの平坦化はリスト — flatMap() / flatten()を、畳み込みはリスト — reduce() / fold()を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。