Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ### タプルを使う
- タプルは複数の違う型の要素を格納して1つの値にするために使う。
- タプルは丸括弧で値を囲み、要素をカンマで区切る。
- ```
- scala> (1, 3)
- res77: (Int, Int) = (1,3)
- scala> (3, 'a', "hello")
- res78: (Int, Char, String) = (3,a,hello)
- scala> (50, 50.4, "hello", 'b')
- res79: (Int, Double, String, Char) = (50,50.4,hello,b)
- ```
- 2次元ベクトルを表すときにリストを使うと、List(List(1,2), List(8,11,5), List(4,5))というように要素数の異なるリストを混ぜることができてしまう。
- これに対し、サイズ2のタプル(ペアとも呼ばれる)とサイズ3のタプルはそれぞれ違う型として扱われる。返り値として期待する型を指定しておくことでコンパイルエラーとすることができる。
- ```
- scala> List((1,2), (8,11,5), (4,5))
- res80: List[Product with Serializable] = List((1,2), (8,11,5), (4,5))
- scala> val xs: List[(Int, Int)] = List((1,2), (8,11, 5), (4,5))
- <console>:7: error: type mismatch;
- found : (Int, Int, Int)
- required: (Int, Int)
- val xs: List[(Int, Int)] = List((1,2), (8,11, 5), (4,5))
- ```
- 長さが同じで違う型のタプルも同じ同様。
- ```
- scala> List((1, 'a'), ('b', 2))
- res83: List[(AnyVal, AnyVal)] = List((1,a), (b,2))
- scala> val xs: List[Int, Char] = List((1, 'a'), (2, 'b'))
- <console>:7: error: wrong number of type arguments for List, should be 1
- val xs: List[Int, Char] = List((1, 'a'), (2, 'b'))
- ^
- ```
- タプルは固定長。あらかじめ必要とする要素の数が分かっている場合にだけ利用できる。Scalaでは要素数が22個のタプルまでしか作ることができないので注意。
- ```
- scala> (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)
- res85: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)
- scala> (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23)
- <console>:8: error: object <none> is not a member of package scala
- (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23)
- ^
- ```
- ### ペアを使う
- 2要素のタプルをペアと呼ぶ。
- `_1`, `_2`がペアの最初の要素と2つ目の要素を返す。
- ```
- scala> (8, 11)._1
- res87: Int = 8
- scala> (8, 11)._2
- res88: Int = 11
- ```
- `zip`メソッドは2つのリストから1つのリストを生成する。2つのリストを同時に走査するときにとても便利。
- ```
- scala> List(1, 2, 3, 4, 5).zip(List(5, 5, 5, 5, 5))
- res89: List[(Int, Int)] = List((1,5), (2,5), (3,5), (4,5), (5,5))
- scala> (1 to 5).toList.zip(List("one", "two", "three", "four", "five"))
- res91: List[(Int, String)] = List((1,one), (2,two), (3,three), (4,four), (5,five))
- ```
- リストの長さが違う場合は必要な分だけが使われ、余りは無視される。
- ```
- scala> List(5, 3, 2, 6, 2, 7, 2, 5, 4, 6, 6).zip(List("im", "a", "turtle"))
- res92: List[(Int, String)] = List((5,im), (3,a), (2,turtle))
- ```
- Streamもzipできる。
- ```
- scala> Stream.from(1).zip(List("apple", "orange", "cherry", "mango")).toList
- res96: List[(Int, String)] = List((1,apple), (2,orange), (3,cherry), (4,mango))
- ```
- ### 直角三角形を見つける
- 次のすべての条件を満たす直角三角形を見つけるプログラムを書く。
- * 3辺の長さはすべて整数である
- * 各辺の長さは10以下である
- * 周囲の長さは24に等しい
- 最初のステップとして、各要素が10以下であるようなトリプルをすべて生成してみる。
- ```
- scala> val triples = for (c <- (1 to 10); a <- (1 to 10); b <- (1 to 10)) yield (a, b, c)
- ```
- 次に直角三角形のみを取得したいので、ピタゴラスの低利が成り立つかを調べる述語を追加。またaが斜辺cを超えないように、bがaを超えないように、それぞれ変更を加える。
- ```
- scala> val rightTriangles = for (c <- (1 to 10); a <- (1 to c); b <- (1 to a) if a*a + b*b == c*c) yield (a, b, c)
- ```
- 最後に周囲の長さが24を取得するための述語を追加。
- ```
- scala> val rightTriangles = for (c <- (1 to 10); a <- (1 to c); b <- (1 to a) if a*a + b*b == c*c && a+b+c == 24) yield (a, b, c)
- rightTriangles: scala.collection.immutable.IndexedSeq[(Int, Int, Int)] = Vector((8,6,10))
- ```
- 答えが出ました!このように、最初に解の候補となる集合を生成し、それから1つ(もしくは複数)の解にたどり着くまで変換とフィルタリングを行うという手法は関数プログラミングでよく用いられるパターン。
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement