相互変換
object Main {
def main(args: Array[String]): Unit = {
// 順序のあるコレクション
// Traversable -> Iterable -> Seq
// -> List
// -> Array
// -> Buffer -> ListBuffer, ArrayBuffer
// -> Vector
// -> Stream
val list = List(1, 2, 3)
// マップ
// Traversable -> Iterable -> Map
val map = Map("a" -> 1, "b" -> 2)
// 集合
// Traversable -> Iterable -> Set
val set = Set(1, 2, 3)
// 相互変換 (マップのみタプルが絡むため特殊)
println(map.toList) //=> List((a,1), (b,2))
println(map.toList.toMap) //=> Map(a -> 1, b -> 2)
println(list.toIterable) //=> List(1, 2, 3)
println(list.toSeq) //=> List(1, 2, 3)
println(list.toList) //=> List(1, 2, 3)
println(list.toArray) //=> [I@35a9cc1a
println(list.toSet) //=> Set(1, 2, 3)
// 生成元がミュータブルであっても、結果はイミュータブルになります。
val mapImmutable = scala.collection.mutable.Map(1 -> 10).toMap
// mapImmutable += (2 -> 20) // エラー
}
}
リスト
走査
object Main {
def main(args: Array[String]): Unit = {
val list = List(1,2,3)
for(e <- list) {
println(e)
}
list.foreach{ e =>
println(e)
}
}
}
ソート
object Main {
def main(args: Array[String]): Unit = {
println(List(3,1,2).sorted) //=> List(1, 2, 3)
println(List("abc", "ab").sortWith{ (x, y) => x.length < y.length }) //=> List(ab, abc)
println(List("abc", "ab").sortBy{ _.length }) //=> List(ab, abc)
}
}
ネストしたリストをフラット化 (または Option 型のリストの処理)
object Main {
def main(args: Array[String]): Unit = {
// ruby の flatten のようなものです
println(List(List(1,2),List(3)).flatten) //=> List(1, 2, 3)
println(List(1,2,3).flatMap { e => // とすると、
List(e, e)
})
//=> List(1, 1, 2, 2, 3, 3)
println(List(1,2,3).map { e => // これと同じ意味。
List(e,e)
}.flatten) // 中間 List も生成せずに高速
//=> List(1, 1, 2, 2, 3, 3)
// Option 型のリストから None を除外する効果
println(List(Some("a"), Some("b"), None).flatten) //=> List(a, b)
}
}
文字列化 (Join)
object Main {
def main(args: Array[String]): Unit = {
val list = List(1,2,3)
println(list.mkString) //=> 123
println(list.mkString("delimiter")) //=> 1delimiter2delimiter3
println(list.mkString("pre", "delimiter", "post")) //=> pre1delimiter2delimiter3post
}
}
集約
object Main {
def main(args: Array[String]): Unit = {
// ruby の inject のようなものです
println(List("b", "c").foldLeft("a") { (l, e) =>
l + e
}) //=> abc ("a" は l の初期値)
println(List("a", "b").foldRight("c") { (e, r) =>
e + r
}) //=> abc ("c" は r の初期値)
// (("a" + "b") + "c")
println(List("a", "b", "c").reduceLeft { (l, e) =>
l + e
}) //=> abc
// ("a" + ("b" + "c"))
println(List("a", "b", "c").reduceRight { (e, r) =>
e + r
}) //=> abc
// リストが空 List() の場合に例外を投げたくない場合
println(None.reduceLeftOption { (l: Any, e: Any) =>
}) //=> None
println(List(1,2,3).reduceRightOption { (e: Int, r: Int) =>
e + r
}) //=> Some(6)
}
}
分割
object Main {
def main(args: Array[String]): Unit = {
// 条件式 (true/false) で二つのリストに仕分け
println(List(-1,2,-3).partition{ _ > 0 }) //=> (List(2),List(-1, -3))
// 式の結果で複数のリストに仕分け
println(List(-1,2,-3).groupBy{ _ > 0 }) //=> Map(false -> List(-1, -3), true -> List(2))
// インデックス番号 i で二つのリスト (0..i-1, i..-1) に分割
val (listA, listB) = List("a", "b", "c").splitAt(2)
println(listA) //=> List(a, b)
println(listB) //=> List(c)
}
}
Zip (タプルを利用した処理)
object Main {
def main(args: Array[String]): Unit = {
// ruby の each_with_index のようなものです
List("a", "b", "c").zipWithIndex.foreach{ tuple =>
println(tuple) //=> (a,0), (b,1), (c,2)
}
// 長さが一致しない場合、超過した要素は捨てられます
val zipped = List(1,2,3,4).zip(List("a", "b", "c"))
val unzipped = zipped.unzip
println(zipped) //=> List((1,a), (2,b), (3,c))
println(unzipped) //=> (List(1, 2, 3),List(a, b, c))
}
}
集合
昔、数学 A で出会った集合です。
object Main {
def main(args: Array[String]): Unit = {
val set = Set(1,2,3)
// 要素の追加
val set2 = set + 4
println(set2) //=> Set(1, 2, 3, 4)
println(set2 + 4) //=> Set(1, 2, 3, 4) (重複して追加はされない)
// 要素の削除
println(set - 1) //=> Set(2, 3)
println(set - 0) //=> Set(1, 2, 3) (存在しない要素を指定してもエラーにはならない)
println(set.filter{ _ != 1 }) //=> Set(2, 3)
// 和集合
println(set | Set(4,5,6)) //=> Set(5, 1, 6, 2, 3, 4) ←(A ∪ B)
println(set ++ Set(4,5,6)) // としても Set では同じ意味
// 積集合
println(Set(1,2) & Set(2)) //=> Set(2) ←(A ∩ B)
// 差集合
println(set -- Set(1)) //=> Set(2, 3)
// 走査
set.foreach{ e =>
println(e) //=> 1 => 2 => 3
}
// 変換
println(set.map{ _ * 2 }) //=> Set(2, 4, 6)
}
}
マップ
他の言語の連想配列のようなものです。
object Main {
def main(args: Array[String]): Unit = {
val map = Map[Int, Int](1 -> 10, 2 -> 20)
// 値の取得
println(map.get(1)) //=> Some(10)
println(map(2)) //=> 20 (ただし、存在しないキーを指定すると例外)
println(map.getOrElse(0, -1)) //=> -1
// マップはタプルのリストのようなもの
val tuple1 = (1, 10)
val tuple2 = (2, 20)
val map2 = Map(tuple1, tuple2) // 1 -> 2 は (1, 2) というタプルを生成する記法
println(map2) //=> Map(1 -> 10, 2 -> 20)
// 要素の追加
val map3 = map + (3 -> 30, 4 -> 40)
println(map3) //=> Map(1 -> 10, 2 -> 20, 3 -> 30, 4 -> 40)
// マップの連結
println(Map(1->10) ++ Map(2->20)) //=> Map(1 -> 10, 2 -> 20)
// 要素の削除
println(Map(1->10, 2->20) - 1) //=> Map(2 -> 20)
println(Map(1->10, 2->20, 3->30, 4->40) - (1,3,4)) //=> Map(2 -> 20)
println(Map(1->10, 2->20, 3->30, 4->40) -- List(1,3,4)) //=> Map(2 -> 20)
println(Map(1->10,2->20).filter{ case(key,value) =>
key == 2
}) //=> Map(2 -> 20)
// 走査
map.foreach{ e =>
println(e._1 + e._2) //=> 11 => 22 (タプルのループ)
}
map.foreach{ case(key, value) =>
println(key + value) // としても同じ
}
println(map.keys) //=> Set(1, 2)
println(map.values) //=> MapLike(10, 20)
// 長さ
println(map.size) //=> 2
// 含まれるか、空かどうか
println(map.contains(0)) //=> false
println(map.isEmpty) //=> false
println(map.nonEmpty) //=> true
// 変換 (map の map と書くと混乱する)
println(Map(1->10, 2->20).map{ case(key,value) =>
(key, value * 2)
}) //=> Map(1 -> 20, 2 -> 40)
println(Map(1->10, 2->20).map{ case(key,value) =>
key
}) //=> List(1, 2)
// ソート (キーを List に変換してソート)
val sortedKeys = map.keys.toList.sorted
sortedKeys.foreach{ key =>
println(map(key)) //=> 10 => 20
}
}
}
ストリーム
参考: 具象不変コレクションクラス
ストリーム (Stream) はリストに似ているが、要素は遅延評価される。そのため、ストリームは無限の長さをもつことができる。呼び出された要素のみが計算される。他の点においては、ストリームはリストと同じ性能特性をもつ。
object Main {
def main(args: Array[String]): Unit = {
// a, b, a+b, b+(a+b),...
def fibFrom(a: Long, b: Long): Stream[Long] = {
a #:: fibFrom(b, a + b) // ストリームの先頭への要素の追加
}
val fibs = fibFrom(1,1) // 無限長
println(fibs) //=> Stream(1, ?)
for(i <- 0 to 10) {
println(fibs(i))
}
// リストでは実現できません。
def fibFromList(a: Long, b: Long): List[Long] = {
a +: fibFromList(b, a + b) // リストの先頭への要素の追加
}
// val fibsList = fibFromList(1,1) // 無限長リストは無限にメモリを必要とする
//=> java.lang.StackOverflowError
}
}
その他の話題
比較
コレクションの値の比較は ==
と !=
です。Seq
は順序まで一致している必要がありますが、Set
と Map
はその必要はありません。
ミュータブルなコレクション
Scala のコレクションは要素の追加や削除を行うときは別のインスタンスを生成する、という考えのもと既定ではイミュータブルな型です。import scala.collection.mutable._
によってミュータブルなものが利用できるようになります。
// イミュータブルな型と併用する場合はここまで import するとよい
import scala.collection.mutable
object Main {
def main(args: Array[String]): Unit = {
// 集合
val setMutable = mutable.Set()// 参照先は変更されるが「参照」は変更されないため val で問題ない。
// マップ
val mapMutable = mutable.Map[Int,Int]()
mapMutable += (1 -> 1)
println(mapMutable) //=> Map(1 -> 1)
// 配列
// val arrMutable = mutable.Array[Int]() // これは間違い
val arrMutable = mutable.ArrayBuffer[Int]() // ArrayBuffer がミュータブルな配列
// リスト
// val listMutable = mutable.List[Int]() // これは間違い
val listMutable = mutable.ListBuffer[Int]() // ListBuffer がミュータブルなリスト
}
}
0
記事の執筆者にステッカーを贈る
有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。
さらに詳しく →Feedbacks
ログインするとコメントを投稿できます。
関連記事
- Scala 文字列の処理書式指定 object Main { def main(args: Array[String]): Unit = { println("%d + %d = %d".format(1, 1, 2)) //=> 1 + 1 = 2 } } 文字列の比較 ヒアドキュメント 他の言語でいう「ヒアドキュメント」のようなものは """ で囲うことで実現できます。 object Main ...
- Scala 日付に関する処理Date クラスを文字列にフォーマット import java.util.Date object Main { def main(args: Array[String]): Unit = { // format は Date に限らない文字列用の機能です。 println("%d-%d-%d" format (1, 1, 1)) //=> 1-1-1 printl...
- 酢豚の基本的な使い方 (sbt)sbt は Scala および Java を主な対象としたビルドツールです。Scala Build Tool の略ではありませんが、Simple Build Tool という明示的な記述も公式ドキュメントなどには見当りません。以下 sbt の基本的な使用例をまとめます。使用した sbt のバージョンは 0.13 です。 公式ドキュメント [sbt 0.13](http://www.scala-sb...
- Scala 関数のサンプルコード「デフォルト引数」および「Unit 型を返す関数」 object HelloWorld { def main(args: Array[String]): Unit = { def myPrint(myArg: String = "default_value") = println(myArg + "!") val result = myPrint() //=> defau...
- Scala 組み込みの制御構造if-else 条件分岐で知られる if-else は三項演算子のようにも使用されます。 object HelloWorld { def main(args: Array[String]): Unit = { val myVal = if (!args.isEmpty) args(0) else "default" println(myVal) } ...