LoginSignup
1
0

More than 1 year has passed since last update.

ScalaのListの操作

Last updated at Posted at 2022-12-08

はじめに

現在Scalaを勉強中の大学生です.Scalaを勉強するにあたって自分なりに知識を整理したり簡潔にまとめたりしたいと思い,この記事を書いています.
この記事では,Scala スケーラブルプログラミングの第16章のリストの操作で出てきた項目をまとめています.なお,参考書籍は現在第4版が出ており,使用しているのが第3版なので少し情報が古いかもしれません.
これまでにC++とPythonしかやってきていないので正直めちゃくちゃ苦戦しています.
間違ってるところもあるかもしれないですが,その場合は教えてください.

List型

リストはイミュータブル(変更不可)であり,代入を用いて要素の変更はできません.つまり,

val fruit:List[String] = ("apple", "orange", pears")

というコードに対して

fruit(0) = "grape"

とすることはできません.
また,タプルとは異なり要素は全て同じ型にしなければなりません(等質的?).
さらに,リスト型は,例えばある型Tとそのサブ型Sがあった時,List[S]もList[T]のサブ型になります(共変).なので,List[String]はList[Object]のサブ型であり,List[Nothing]はすべての型のサブ型になります.空のリストList()の型はList[Nothing]です.空のリストはNilと書くこともできます.

val xs:List[String] = List()
/*List()はList[Nothing]型であり,List[String]とは型が異なるが,
NothingはStringのサブ型なのでこれが可能になる.*/

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

操作一覧(一階メソッド)

ここからは操作方法をまとめます.ここで用いる変数は以下です.

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) 右のリストの先頭に左の要素を追加する.
head fruit.head apples リストの先頭要素を返す.空の要素ではエラーが出る.
last fruit.last oranges リストの最後の要素を返す.空の要素ではエラーが出る.
tail fruit.tail List(oranges) 先頭要素以外の要素から成るリストを返すもし要素が一つならList()が返ってくる.
init fruit.init List(apples) 最後の要素以外の要素から成るリストを返す.もし要素が一つならList()が返ってくる.
isEmpty fruit.isEmpty
empty.isEmpty
false
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 イテレータを返す.nextを使うことで要素に順にアクセスしていく.

操作一覧(高階メソッド)

ここで用いる変数は以下です.

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
quick
brown
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)
nums.forall(_>0)
false
true
リスト内の全ての要素がBooleanを満たす(true)場合trueを,そうでない場合falseを返す.
exists nums.exists(_==2)
nums.exists(_<0)
true
false
リスト内にBooleanを満たす要素が存在すればtrue, 存在しなければfalseを返す.
foldLeft nums.foldLeft(0)(_+_)
nums.foldLeft(List[Int]())((x, y) => y::x)
15
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)
List.range(1, 9, 2)
List(1, 2, 3, 4)
List(1, 3, 5, 7)
引数が2つの時は1つ目の値から2つ目の値-1までの全ての整数のリストを作成する.3つの時は,1つ目の値から2つ目の値-1まで,3つ目の値ずつ加えたリストを作成する.
List.fill List.fill(5)('a')
List.fill(2,3)('a')
List(a, a, a, a, a)
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) 複数の要素リストを連結する.空リストは無視される.引数に何も渡さなければ空のリストが生成される.
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0