Kotlinの多次元配列、もう一つの落とし穴:縦には弱い!
随分前にKotlinの多次元配列でImmutableなものを作成しようとして困った話を書いた。
同時に配列やその他のコレクションについて様々な操作関数が用意されているが、ほぼ一次元のものに限定されているとも書いた。
その状況はそろそろバージョンが1.4になろうかという現在でも同じようである。
KotlinでK-V的な行列データを読み取る
人間がKey-Value的なものを配列やListで実現しようとするとまず想像するのがExcelの表のようなもので
日付 | データ |
---|---|
1月1日 | 500 |
1月2日 | 699 |
1月5日 | 350 |
1月6日 | 460 |
のように1列目にKey、2列目にValueを配置して縦に伸ばしていくことを考えるだろう。
そして3月4日の値はなんだろう、といって1列目をKeyにして検索し、対応する2列目の値を調べる。それが自然なやり方だと思う。
Kotlinの2次元配列においてインデックスはArray[縦][横]のように指定できる。ちなみにインデックスは0始まり。
だから3月4日の値を調べたかったら1列目に検索を掛けて3月4日の値を持っているインデックスを探し、2列目の値を取得すればいい、ということになる。
だがこの方法は上手くいかない。
その理由はKotlinの行列は縦に検索することができないから、ということだ。
だからこういったことをやるためには行列を転置して縦横を逆にした行列を用いなくてはならないのだ。
1月1日 | 1月2日 | 1月5日 | 1月6日 |
---|---|---|---|
500 | 699 | 350 | 460 |
のような行列にして1行目を検索、そのインデックスで2行目の値を取得するという持って回ったような手法が必要なのである。
具体的なコードは以下のようなものになるだろう。
fun main() {
var twoDarr = arrayOf>()
var arr1d1 = arrayOf("1/1", "1/2", "1/5", "1/6")
var arr1d2 = arrayOf("500", "699", "350", "460")
twoDarr += arr1d1
twoDarr += arr1d2
println(twoDarr[0].indexOf("1/2"))
println(twoDarr[1][twoDarr[0].indexOf("1/2")])
}
結果はそれぞれ1, 699となる。
実際にはこの二次元配列はExcelで作成したCSVなどから読み取ったものになるだろう。
現実的な解としてはExcelでは縦に作成し、それをKotlinに読み込む際、転置すると言うものが挙げられる。KotlinでCSVを処理するためのライブラリ関数があるようなので、その扱い方を含めていつか記載しようと思う。
まとめ
Kotlinの行列は縦に検索できないので検索が必要な成分は横に並べる必要がある。
CSVのような古典的で扱いやすいデータを元にしてプログラムを動かそうとするとき、これもまた一つの落とし穴になるので記載しておいた。