Scalaのコレクションとかについて


## コレクションのクラス関連図

> Traverable : 操作可能なコレクション
>> → Iterable : 繰り返し可能なコレクション
>>>
→ Set : 重複を含まない集合
→ Map : キーと値のペアの集合
→ Seq : 順序のある集合
>>>> → IndexedSeq : VectorやRangeなど、ランダムアクセス？
→ LinearSeq : Listなど、順次アクセス？
→ Buffer : 遅延評価？

# Seq
## Range

範囲を持つ数値を表現するクラス。ループ処理やList生成で使える。
*Range(start, end, step)* あるいは、 *until/to* と *by* を使って生成できる。

>
scala> Range(0, 10, 2)
res5: scala.collection.immutable.Range = Range(0, 2, 4, 6, 8)
scala> 0 to 10 by 2
res6: scala.collection.immutable.Range = Range(0, 2, 4, 6, 8, 10)
scala> 0 until 10 by 2
res7: scala.collection.immutable.Range = Range(0, 2, 4, 6, 8)

生成される範囲が違うところに注意が必要。

*to/until* はfor文で使うと使いやすい。
>
scala> for (i <- 1 to 3) { println("id:" + i) }
id:1
id:2
id:3

*toList*でList型に変換することもできる。
>
scala> (1 to 10).toList
res15: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

## List

### 生成

要素同士を連結するデータ構造のリスト
順次アクセスや再帰呼び出しに強い
ランダムアクセスは遅い

ファクトリメソッドや *::* を利用して生成する。
*::* は既存のリストに要素を連結するメソッドなので、元となる空リスト（ *Nil* ) が必要
>
scala> List("taro","jiro","hoge")
res19: List[String] = List(taro, jiro, hoge)
>
scala> "taro"::"jiro"::"hoge"::Nil
res21: List[String] = List(taro, jiro, hoge)

### Listに対する基本操作

##### 先頭に要素追加 ( *::* / *+:* )
>
scala> 3 +: (1 to 5).toList
res1: List[Int] = List(3, 1, 2, 3, 4, 5)
scala> 3 :: (1 to 5).toList
res2: List[Int] = List(3, 1, 2, 3, 4, 5)

##### 末尾に要素追加 ( *:+)
>
scala> (1 to 5).toList :+ 6
res5: List[Int] = List(1, 2, 3, 4, 5, 6)

##### List同士を連結 ( *:::* )
>
scala> (1 to 5).toList ::: (6 to 10).toList
res19: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

:: で連結すると入れ子になってしまう。
>
scala> (1 to 5).toList :: (6 to 10).toList
res21: List[Any] = List(List(1, 2, 3, 4, 5), 6, 7, 8, 9, 10)


##### インデックス指定で取得
>
scala> (1 to 5).toList(3)
res3: Int = 4

##### 一部を取得
head : 先頭
last : 末尾
init : 末尾以外
tail : 先頭以外
slice : 範囲指定
>
scala> (1 to 5).toList.head
res7: Int = 1
scala> (1 to 5).toList.last
res8: Int = 5
scala> (1 to 5).toList.init
res10: List[Int] = List(1, 2, 3, 4)
scala> (1 to 5).toList.tail
res9: List[Int] = List(2, 3, 4, 5)
scala> (1 to 5).toList.slice(2,4)
res13: List[Int] = List(3, 4)

##### 要素数
size : 要素数
isEmpty/nonEmpty : 空かどうか判断

>
scala> (1 to 5).toList.size
res14: Int = 5
scala> (1 to 5).toList.isEmpty
res15: Boolean = false
scala> (1 to 5).toList.nonEmpty
res17: Boolean = true


### ソート

逆順にする。
>
scala> (1 to 10).toList.reverse
res13: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

ソート
>
scala> List(3,1,4,5).sorted
res15: List[Int] = List(1, 3, 4, 5)

### filter

引数に判定式を渡すことで、要素の削除ができる。
>
scala> (1 to 10).toList.filter(_ % 2 == 0)
res24: List[Int] = List(2, 4, 6, 8, 10)
scala> (1 to 10).toList.filterNot(_ % 2 == 0)
res25: List[Int] = List(1, 3, 5, 7, 9)

### foreach

リストの要素を繰り返し処理する。
>
scala> (1 to 3).toList.foreach( e => println("id:" + e) )
id:1
id:2
id:3

### zipWithIndex

リストを添え字付きのタプルに変換する。
>
scala> List("taro","jiro").zipWithIndex
res0: List[(String, Int)] = List((taro,0), (jiro,1))

繰り返し処理で添字が必要になる場合などに使える。
>
scala> List("taro","jiro").zipWithIndex.foreach{ case(e:String,i:Int) => println("%d:%s".format(i,e)) }
0:taro
1:jiro

### map/collect

リストの内容を変換する。
>
scala> List("taro","jiro").map{ "[" + _ + "]" }
res5: List[String] = List([taro], [jiro])

collectを利用するとcaseの条件に一致した要素のみ抽出できる。
以下の例はString型のみ文字列変換を行っている。
>
scala> List(1,"taro",2,"jiro").collect{ case(e:String) => "[" + e + "]" }
res9: List[String] = List([taro], [jiro])

### reduce/fold

リストに対して集計処理を行う。
初期値なし : reduceLeft/reduceRight
初期値あり : foldLeft/foldRight
>
scala> (1 to 10).toList.reduceLeft{ _ + _ }
res5: Int = 55
scala> (1 to 10).toList.foldLeft(1){ _ + _ }
res6: Int = 56

内部的には (((1+2)+3)+4)...という処理を行っている。

### zip/unzip

リスト同時を並列に結合して、ペアのリストを作る。

>
scala> (1 to 10 by 2).toList.zip( 2 to 10 by 2 )
res9: List[(Int, Int)] = List((1,2), (3,4), (5,6), (7,8), (9,10))


## Map

タプル型を渡すことでMapを生成できる。
>
scala> Map( ("taro", "hoge"),("jiro", "piyo") )
res14: scala.collection.immutable.Map[String,String] = Map(taro -> hoge, jiro -> piyo)

*Map(key->value)* 形式でも生成可能。
-> はタプルを生成するメソッド
getメソッドで値を取得

>
scala> val map = Map("taro"->"hoge", "jiro"->"piyo")
map: scala.collection.immutable.Map[String,String] = Map(taro -> hoge, jiro -> piyo)
>
scala> map.get("taro")
res11: Option[String] = Some(hoge)

Map.getの戻り値はOption型、キーが存在しない場合はNoneとなる。
>
scala> map.get("naiyo")
res12: Option[String] = None

## Set