ScalaのListの操作

# はじめに
現在Scalaを勉強中の大学生です．Scalaを勉強するにあたって自分なりに知識を整理したり簡潔にまとめたりしたいと思い，この記事を書いています．
この記事では，[Scala スケーラブルプログラミング](https://www.amazon.co.jp/Scala%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%A9%E3%83%96%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E7%AC%AC3%E7%89%88-Martin-Odersky/dp/4844381490/ref=pd_lpo_2?pd_rd_w=dQ789&content-id=amzn1.sym.d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_p=d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_r=CFX8HBS7PE3PFDXPN8QG&pd_rd_wg=M4J8I&pd_rd_r=7ed80cdc-7c9e-48c5-92f5-7cd8dfba536e&pd_rd_i=4844381490&psc=1)の第16章のリストの操作で出てきた項目をまとめています．なお，参考書籍は現在第4版が出ており，使用しているのが第3版なので少し情報が古いかもしれません．
これまでにC++とPythonしかやってきていないので正直めちゃくちゃ苦戦しています．
間違ってるところもあるかもしれないですが，その場合は教えてください．

# List型
リストはイミュータブル(変更不可)であり，代入を用いて要素の変更はできません．つまり，
```scala
val fruit:List[String] = ("apple", "orange", pears")
```
というコードに対して
``` scala
fruit(0) = "grape"
```
とすることはできません．
また，タプルとは異なり要素は全て同じ型にしなければなりません(等質的?)．
さらに，リスト型は，例えばある型Tとそのサブ型Sがあった時，List[S]もList[T]のサブ型になります(共変)．なので，List[String]はList[Object]のサブ型であり，List[Nothing]はすべての型のサブ型になります．空のリスト`List()`の型はList[Nothing]です．空のリストは`Nil`と書くこともできます．
```scala
val xs:List[String] = List()
/*List()はList[Nothing]型であり，List[String]とは型が異なるが，
NothingはStringのサブ型なのでこれが可能になる．*/

println(List() == Nil) //true
```

# 操作一覧(一階メソッド)
ここからは操作方法をまとめます．ここで用いる変数は以下です．
```scala
val fruit:List[String] = List("apples", "oranges")
val abcde:List[char] = List('a', 'b', 'c', 'd', 'e')
val empty:List[Nothing] = List()
val zipped:List[(Char, Int)] = List(('a', 1), ('b', 1), ('c', 1))
val arr = new Array[Int](7) //Array(0, 0, 0, 0, 0, 0, 0)
```
使用例はあくまで一例です．また，`hoge.method(arg)`の形で書いているものは，`hoge method arg`のように中置き演算子の形でかけるものもあります．
(表の幅の調節方法がわからなかったです！！教えてください!!!)
|メソッド|使用例|結果|効果|
|:--|:--|:--|:--|
|::|`val fruit = "apples"::"oranges"::Nil`|val fruit: List[String] = List(apples, oranges)|右のリストの先頭に左の要素を追加する．|一番右の要素はリストにしておかなければならない(今回はNil)|
|head|`fruit.head`|apples|リストの先頭要素を返す．空の要素ではエラーが出る．|
|last|`fruit.last`|oranges|リストの最後の要素を返す．空の要素ではエラーが出る．|
|tail|`fruit.tail`|List(oranges)|**先頭要素以外**の要素から成るリストを返すもし要素が一つならList()が返ってくる．|
|init|`fruit.init`|List(apples)|**最後の要素以外**の要素から成るリストを返す．もし要素が一つならList()が返ってくる．|
|isEmpty|`fruit.isEmpty`<br>`empty.isEmpty`|false<br>true|リストが空ならtrue, そうでなければfalseを返す．||
|:::|List(1, 2):::List(3, 4, 5)|List(1, 2, 3, 4, 5)|2つのリストを結合する．||
|length|`fruit.length`|2|リストの長さを計算する．リスト全体を辿って末尾まで数えるので，コストが高い．|
|reverse|`fruit.reverse`|List(oranges, apples)|リストの要素の順番を反転する．リストを書き換えるのではなく，新しいリストを作成する．頻繁な末尾へのアクセスに有効．|
|take|`abcde.take(2)`| List(a, b)|先頭から指定した個数の要素数までのリストを返す．lengthより大きい数を指定するとリスト全体が返ってくる．|
|drop|`abcde.drop(2)`|List(c, d, e)|先頭から指定した個数までの要素以外の要素を返す．lengthより大きい数を指定すると空のリストが返ってくる．|
|splitAt|`abcde.splitAt(2)`|(List(a, b), List(c, d, e))|指定された添字の位置でリストを分割し，2個のリストのタプルを返す．lengthより大きい数を指定すると(リスト全体， 空のリスト)というタプルが返ってくる．|
|apply|`abcde.apply(2)`|c|添字の位置の要素が返ってくる．省略して`abcde(2)`でも良い．|
|indices|`abcde.indices`|Range 0 until 5|リストで有効なすべての添字から成るリストを返す．||
|flatten|`List(List(1, 2), List(3, 2)).flatten`|List(1, 2, 3, 2)|複数のリストの要素をまとめた1つの要素にする．要素が全てリストでないといけない．それ以外はエラーがでる．|
|zip|`abcde.zip(fruit)`|List((a, apples), (b, oranges))|2個のリストからタプルのリストを1つ作る．2つのリストの長さが異なる場合，相手のない要素は捨てられる．|
|zipWithIndex|`fruit.zipWithIndex`|List((apples, 0), (oranges, 1))|添字とリストからタプルのリストを作成する．`fruit.zip(fruit.indices)`と同じ|
|unzip|`zipped.unzip`|(List(a, b, c), List(1, 2, 3))|タプルのリストをリストのタプルにして返す．||
|toString|`abcde.toString`|"List(a, b, c, d, e)"|文字列として返す．結果として示しているのはList型ではなくStringであることに注意.(わかりやすくするために""で囲んでいます．|
|mkString|`abcde.mkString("pre ", " sep ", " pos")`|pre a sep b sep c sep d sep e pos|先頭にpre, 要素間にsep, 末尾にposを加えた文字列を返す．preとposを省略することもできる．その場合sepで繋がれた文字列が返る．
|toArray|`abcde.toArray`|Array(a, b, c, d, e)|リストを配列にする．配列をリストにするにはtoList|
|copyToArray|`List(1, 2, 3).copyToArray(arr, 3)`|Array(0, 0, 0, 1, 2, 3, 0)|指定した配列の指定したインデックスの位置以降に要素をコピーする．配列はコピーが入る大きさでないといけない．|
|iterator|abcde.iterator|<iterator>|イテレータを返す．nextを使うことで要素に順にアクセスしていく．|


# 操作一覧(高階メソッド)
ここで用いる変数は以下です．
```scala
val words = List("the", "quick", "brown", "fox")
val nums = List(1, 2, 3, 4, 5)
```
|メソッド|使用例|結果|効果|
|:--|:--|:--|:--|
|map|`words.map(_.toList)`|List(List(t, h, e), List(q, u, i, c, k), List(b, r, o, w, n), List(f, o, x))|個々の要素に関数を適用した結果値を要素とするリストを返す．(toListは文字列に対しては一文字ずつを要素に持つリストに変換．)|
|flatMap|`words.flatMap(_.toList)`|List(t, h, e, q, u, i, c, k, b, r, w, o, n, f, o, x)|処理後の要素のリストを全て連結した一つのリストを返す．|
|foreach|`nums.foreach(println(_))`|the<br>quick<br>brown<br>fox|各要素に対して引数の演算/処理を行う．|
|filter|`nums.filter(_%2==0)`|List(2, 4)|Boolean型関数をとり，それがtrueになる要素を集めたリストを返す．存在しなければ空のリストが返る．|
|partition|`nums.partition(_%2 == 0)`|(List(2, 4), List(1, 3, 5))|Booleanの結果がtrueになる要素から成るリストと，falseから成るリストのタプルを返す．|
|find|`nums.find(_%2==0)`|Some(2)|Booleanの結果がtrueになる最初の要素を返す．返されるのはオプション値存在しなければNoneが返る．|
|takeWhile|`nums.takeWhile(_ < 3)`|List(1, 2)|先頭からBooleanの結果が連続してtrueになる要素までのリストを返す．存在しなければ空のリストが返る．|
|dropWhile|`words.dropWhile(_.startsWith("t"))`|List(quick, brown, fox)|先頭からBooleanの結果が連続してtrueである要素を削除して残りのリストを返す．存在しなければ空のリストが返る．|
span|`nums.span(_ < 3)`|(List(1, 2), List(3, 4, 5))|Booleanの結果が連続してtrueである要素と，残りの要素それぞれのリストのペアを返す．|
|forall|`nums.forall(_==2)`<br>`nums.forall(_>0)`|false<br>true|リスト内の全ての要素がBooleanを満たす(true)場合trueを，そうでない場合falseを返す．|
|exists|`nums.exists(_==2)`<br>`nums.exists(_<0)`|true<br>false|リスト内にBooleanを満たす要素が存在すればtrue, 存在しなければfalseを返す．||
|foldLeft|`nums.foldLeft(0)(_+_)`<br>`nums.foldLeft(List[Int]())((x, y) => y::x)`|15<br>List(5, 4, 3, 2, 1)|カリー化された1つ目の引数に初期値を指定する．2つ目の引数には，処理を記入する．その際，左は(更新された)初期値，右はリストのになり，初期値を右の値で更新していく．|
|foldRight|` nums.foldRight(List[Int]())((x, y)=>y:::List(x))`|List(5, 4, 3, 2, 1)|foldLeftとは逆に，2つ目の引数のなかの左はリストの値，右は(更新された)初期値であり，初期値を左の値で更新していく．|
|sortWith|`List(9, 2, 4, 3, 1).sortWith(_<_)`|List(1, 2, 3, 4, 9)|引数の条件でソートする．マージソートで実行する(らしい)．|

# Listオブジェクトのメソッド
これまでのはListクラスのメソッドとして実装されていたものだったが，ここからはListクラスのコンパニオンオブジェクトでありグローバルにアクセスできるListオブジェクトのメソッドについて扱います．

|メソッド|使用例|結果|効果|
|:--|:--|:--|:--|
|apply|`List.apply(1, 2, 3)`|List(1, 2, 3)|applyの引数を要素に持つリストを作成．省略できる．|
|range|`List.range(1, 5)`<br>`List.range(1, 9, 2)`|List(1, 2, 3, 4)<br>List(1, 3, 5, 7)|引数が2つの時は1つ目の値から2つ目の値-1までの全ての整数のリストを作成する．3つの時は，1つ目の値から2つ目の値-1まで，3つ目の値ずつ加えたリストを作成する．|
|List.fill|`List.fill(5)('a')`<br>`List.fill(2,3)('a')`|List(a, a, a, a, a)<br>List(List(b, b, b), List(b, b, b))|第1引数の次元であり，第2引数の要素のみで構成されたリストを作成する．|
|tabulate|`List.tabulate(5)(n=>n*n)`|List(0, 1, 4, 9, 16)|第1引数の次元であり，第2引数の関数の計算結果を要素とするリストを作成する．|
|concat|`List.concat(List('a', 'b'), List('c'))`|List(a, b, c)|複数の要素リストを連結する．空リストは無視される．引数に何も渡さなければ空のリストが生成される．|