2011年9月17日土曜日

[scala]Listの色々

Listの操作のまとめ。

Listの生成

    // listの生成
    val list = 1::2::Nil            // Nilは、終端を示す
    val list2 = List("1", "2", "3")

    // 空のlistの生成
    val emp = Nil

パターンマッチでの分解

      val list = List(1, 2, 3)

      // Listの各要素を変数に分解
      // Listの要素数と、展開先の要素数が一致している必要がある。
      val List(n1, n2, n3) = list
      println("n1 = " + n1)    // 1
      println("n2 = " + n2)    // 2
      println("n3 = " + n3)    // 3

      // Listの要素が不確定の場合は、::(コンスと呼ぶらしい)を使って展開する。
      // この例だと1つ目の要素がnに代入され、残りの要素がListとしてnxに代入される。
      val n::nx = list
      println(n)                      // 1
      println("nx = " + nx)      // List(2, 3)

      // caseをつかったパターンマッチ
      list match {
        case List() => println("空のList")
        case n::nx => {
          println(n)           // 1
          println(nx)         // List(2, 3)
        }
      }

Listの結合

      val list = List(1, 2, 3)

      // :::を使ってList同士を結合出来る。
      val list2 = list ::: 1 :: 2 :: 3 :: Nil
      println("list2 = " + list2)    // List(1, 2, 3, 1, 2, 3)

Listのサイズ

Listの要素数は、lengthメソッドで取得出来ます。
      val list = List(1, 2, 3)

      list.length   // 3

lengthメソッドは要素数に比例してコストが高くなるらしいので要素が空か判定する場合には、length == 0ではなくisEmptyを使った方がよいそうです。
実際にListのコード見てみると要素が空になるまでtail(先頭の要素を除外したListを返すメソッド)してるのでかなりコスト高そう・・・。
  def length: Int = {
    var these = self
    var len = 0
    while (!these.isEmpty) {
      len += 1
      these = these.tail
    }
    len
  }

先頭、末尾へのアクセス

      val list = List(1, 2, 3)
      // 先頭の要素
      list.head    // 1
      // 先頭の要素を取り除いたList
      list.tail       // List(2, 3)
      // 最後の要素
      list.last      // 3
      // 最後の要素を取り除いたList
      list.init       // List(1, 2)
※最後の要素へアクセスするlastやinitはlengthと同じようにコストが高くつく。頻繁に末尾要素へアクセスする場合には、事前にreverseメソッドで要素を逆転するのがよいみたいです。

その他

      val list = List('a', 'b', 'c')
      // mapメソッド
      // 引数で指定された関数の結果から新たなListを生成する。
      // この例だと、list変数の各要素を大文字に変換したListを生成する。
      val upperList = list.map(_.toUpper)

      // Listをもとに繰り返し処理を行う場合には、foreachを使う
      // Javaでのfor文かな
      val builder = StringBuilder.newBuilder
      list.foreach(builder.append(_))
      builder     // abcとなる。

      // 条件に一致する値だけに絞り込んだListを生成する
      val abList = list.filter(c => c == 'a' || c == 'b')

      // 条件に一致した最初の要素を返す
      val n = List(1, 2, 3, 4, 5).find(_ % 2 == 0)