なっく日報

技術やら生活やらのメモ

KotlinはListでもDestructuring Declarationsが使える

初めて知ったのでメモ程度に。

Kotlinの Destructuring Declarations(分割代入の機能)

以下の公式ドキュメントにもあるとおり分割代入が使えます。

https://kotlinlang.org/docs/reference/multi-declarations.html

Pairを使った例

val (first, second) = 1 to 2
println("first=$first, second=$second") // first=1, second=2

Map.Entry<K, V> の例

val map = mapOf(
  "k1" => "v1",
  "k2" => "v2"
)
for ((k, v) in map) {
  println("k=$k, v=$v")
}
// k=k1,v=v1
// k=k2,v=v2
  
// ↓でも書ける
// map.forEach { (k, v) ->
//  println("k=$k, v=$v")
// }

data classの例

data class Foo(val first: String, val second: String)
val (first, second) = Foo("first", "second")
println("first=$first, second=$second") // first=1, second=2

実はListでもできる

val (a, b) = listOf(1, 2)
println("a=$a, b=$b") // a=1, b=2

// 利用しない値に代入しないこともできる
val (v) = listOf(1, 2)
println("v=$v") // v=1

// 要素数が少ないと例外が飛ぶ
val (v1, v2) = listOf(1)
// Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
//  at java.util.Collections$SingletonList.get (Collections.java:4815) 

補足

残りの要素数を代入するみたいなことはできないみたい。

ES2015でいうところの↓

const [a, ...b] = [1, 2, 3]; 
console.log(a); // 1
console.log(b); // [ 2, 3 ]

Pythonでいうところの↓

a, *b = [1, 2, 3]
print(a) # 1
print(b) # [2, 3]

無理やりやるなら↓だけど、 元の挙動が変わってしまうので微妙。

operator fun <T> List<T>.component2(): List<T> = drop(1)

val (head, rest) = listOf("one", "two", "three")
println(head) // "one"
println(rest) // ["two", "three"]   

// val (a, b, c)  = listOf("one", "two", "three") が変になる

参考

stackoverflow.com