最近、会社 で Codility をScalaで解く会を毎週昼休みにやっています!
競技プログラミングっぽい問題をScalaで解くときに、個人的に便利だと感じたコレクションメソッドの使い方をまとめてみます!(毎回ググっているので…)
追記:2019/6/22 scanLeftが間違っていました。初期値で設定した値も結果のコレクションに入るのですが、そのようになっていませんでした。失礼しました。
【zipWithIndex】コレクションをforeachなどで走査する際に添え字も使って処理する
zipWithIndex
を使う
val lst = List(3, 10, 1, 6, 9)
lst.zipWithIndex.foreach { v => // vは(要素, 添え字)のタプルになっている
println(s"index: $v.2, value: $v._1")
}
lst.zipWithIndex.foreach { case (value, idx) => // こうやって書くと可読性高い
println(s"index: $idx, value: $value")
}
index: 0, value: 3
index: 1, value: 10
index: 2, value: 1
index: 3, value: 6
index: 4, value: 9
【sorted, sortWith, sortBy】 Seqをソートする
sorted
val lst = List(3, 10, 1, 6, 9)
// 暗黙のOrdering[Int]を引数としてソートされる
lst.sorted // List(1, 3, 6, 9, 10)
sortWith
自分でソート用の関数を定義できる
lst.sortWith((v1, v2) => v1 > v2) // List(10, 9, 6, 3, 1)
sortBy
変換結果の値でソートする
val lst2 = List((3, 6), (10, 1), (1, 2), (6, 5), (9, 4))
// タプルのコレクションをソートするときに便利
lst2.sortBy(_.2) // List((10, 1), (1, 2), (9, 4), (6, 5), (3, 6))
【foldLeft, scanLeft】 たたみ込み
foldLeft
はいつも引数の順番に混乱してしまう…
(累積値, コレクションの値)の順番!
foldLeft
val lst = List(3, 10, 1, 6, 9)
// foldLeft
lst.foldLeft(0) { (acc, v) =>
val newSum = acc + v
println(newSum)
newSum
}
3
13
14
20
29
scanLeft
foldLeftした途中結果を格納したコレクションを返す。
✨累積和をシュッと書ける優れもの✨
val lst = List(3, 10, 1, 6, 9)
val accSum = lst.scanLeft(0)((v1, v2) => v1 + v2) // List(0, 3, 13, 24, 20, 29)
【sliding】 n要素ずつの部分列を見ながら走査する
sliding(size, step)
で、stepずつずらしながらsize個ずつのコレクションを返すようなイテレータを得ることができる
// 隣り合う2要素の和を求める
val itr = List(3, 10, 1, 6, 9).sliding(2)
itr.foreach { slicedList =>
println(slicedList.sum)
}
13
11
7
15
参考
https://www.scala-lang.org/api/current/
http://www.ne.jp/asahi/hishidama/home/tech/scala/collection/method.html
TODO
Stack, Queue, Set, Map関連のメソッドとか、性能特性もまとめたい