LL脳がscalaの勉強を始めたよ その58
Scalaコップ本の17章をやっていきますよー、今回は集合とマップの前半として概要をやりますよー
基本はイミュータブルです( ー`дー´)キリッ
これまでやってきたとおり、Scalaのコレクションではほとんどがimmutableとmutableの両方を持っているものの、immutableなものを使うのがScala的!ということで単純に呼び出された場合はimmutableなオブジェクトが作られました。コレは3章でやったとおり集合(Set)やマップ(Map)も同様ですねー
この「基本はimmutable」ってルールはScalaソースファイルに暗黙にインポートされるPredefオブジェクトによってこんなふうに決められているみたいです
object Predef { // デフォルトでimmutableが呼ばれるように定義されてますな type Set[T] = scala.collection.immutable.Set[T] type Map[K,V] = scala.collection.immutable.Map[K,V] val Set = scala.collection.immutable.Set val Map = scala.collection.immutable.Map //..... }
上記の定義より単純にSetやMapを呼び出した場合はPredef.SetやPredef.Mapを呼び出すことになって、結果的にimmutableなSetやMapを呼び出すことになるみたいですねー。それとtypeキーワードについては20章でやるそうなので一旦放置しますよ。
ちなみにmutableなのを呼び出すときはこんな感じです
// ミュータブルSetを呼び出しますよ scala> import scala.collection.mutable.Set import scala.collection.mutable.Set // 集合定義です scala> Set(1,2,3,4,5) res0: scala.collection.mutable.Set[Int] = Set(5, 3, 1, 4, 2) // ミュータブルMapを呼び出しますよー scala> import scala.collection.mutable.Map import scala.collection.mutable.Map // Mapの定義です scala> Map(1 -> 'a', 2->'b', 3->'c') res1: scala.collection.mutable.Map[Int,Char] = Map(2 -> b, 1 -> a, 3 -> c)
ちなみにこういう呼出をすればimmutableなSetやMapも同時に使えるみたいです
// mutableパッケージで読み込み scala> import scala.collection.mutable import scala.collection.mutable // ミュータブル版を使う場合はこう scala> mutable.Set(1,2,3) res4: scala.collection.mutable.Set[Int] = Set(3, 1, 2) // イミュータブルなものも使えますよ scala> Set(1,2,3) res5: scala.collection.immutable.Set[Int] = Set(1, 2, 3) // ミュータブルMapです scala> mutable.Map(1->'a',2->'b',3->'c') res6: scala.collection.mutable.Map[Int,Char] = Map(2 -> b, 1 -> a, 3 -> c) // イミュータブルなMapです scala> Map(1->'a',2->'b',3->'c') res7: scala.collection.immutable.Map[Int,Char] = Map(1 -> a, 2 -> b, 3 -> c)
集合の使い方
Setは乱暴に言ってしまえば重複がないコレクションですね。正確には==で比較して同じとされる要素が1つしかないというみたいですが…まあ、そんな感じで(´・ω・`)...例えば文章中の単語の種類の数え上げなんかに使えるそうデス。
とりあえずサンプルをやってみますかねー
// ミュータブル版Setを利用するのでインポートします scala> import scala.collection.mutable import scala.collection.mutable // 文章を定義しますよー // ハイパーいい加減な7つ(重複こみ)の単語で構成された文章です scala> val text="Hello world is worldwide in hello world!" text: java.lang.String = Hello world is worldwide in hello world! // 文章を単語で区切って配列に格納しますよー。区切り文字は' '(スペース) ! , . デス scala> val wordsArray = text.split("[ !,.]") wordsArray: Array[java.lang.String] = Array(Hello, world, is, worldwide, in, hello, world) // 空の集合を作成します scala> val words = mutable.Set.empty[String] words: scala.collection.mutable.Set[String] = Set() // 単語を小文字に変換してSetの要素として格納します scala> for(word <- wordsArray) words += word.toLowerCase // 作成されたSetです。単語は全部で5つでした(´・ω・`) scala> words res9: scala.collection.mutable.Set[String] = Set(in, is, world, worldwide, hello)
Setの操作
Setの操作でよくつかわれるものをザザッとやっていきますよー
//// イミュータブル編 // Setの構築 scala> val numSet = Set(1,2,3) numSet: scala.collection.immutable.Set[Int] = Set(1, 2, 3) // 要素を追加しますよ scala> numSet + 5 res10: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 5) // 要素を取り除きますよ scala> numSet - 5 res11: scala.collection.immutable.Set[Int] = Set(1, 2, 3) // 複数の要素を追加しますよ scala> numSet ++ List(5,6) res12: scala.collection.immutable.Set[Int] = Set(5, 3, 1, 6, 2) // 複数の要素を取り除きますよ scala> numSet -- List(1,2) res13: scala.collection.immutable.Set[Int] = Set(3) // 2つの集合の積集合(共通)をとりますよ scala> numSet ** Set(1,3,5,7) res14: scala.collection.immutable.Set[Int] = Set(1, 3) // 集合の要素数をとりますよ scala> numSet.size res15: Int = 3 // 集合に要素が含まれているかどうかを判定しますよ scala> numSet.contains(3) res17: Boolean = true //// ミュータブル編 // ミュータブル版のパッケージを読み込みます scala> import scala.collection.mutable import scala.collection.mutable // 空のミュータブルSetを作りますよ scala> val wordSet = mutable.Set.empty[String] wordSet: scala.collection.mutable.Set[String] = Set() // 要素を追加します scala> wordSet += "the" // 追加結果です scala> wordSet res20: scala.collection.mutable.Set[String] = Set(the) // 要素を取り除きます scala> wordSet -= "the" // 取り除いた結果です scala> wordSet res22: scala.collection.mutable.Set[String] = Set() // 複数要素を追加します scala> wordSet ++= List("do", "re", "mi") scala> wordSet res24: scala.collection.mutable.Set[String] = Set(do, re, mi) // 複数要素を取り除きます scala> wordSet --= List("do", "re") scala> wordSet res26: scala.collection.mutable.Set[String] = Set(mi) // 全ての要素を取り除きます scala> wordSet.clear scala> wordSet res28: scala.collection.mutable.Set[String] = Set()
マップの使い方
マップは乱暴に言ってしまえば任意の種類のキーを使える配列みたいなもんですかね、PHP的連想配列と思っておけば間違いなさそうです。
とりあえずキーと値の対応関係を保持できるマップの操作をいろいろとやってみますかね
// 今回はミュータブル版のMapを使いますよ scala> import scala.collection.mutable import scala.collection.mutable // 空のミュータブルMapを作成します // MapはString => Intの形式になります scala> val map = mutable.Map.empty[String, Int] map: scala.collection.mutable.Map[String,Int] = Map() // キーがhelloで値が1の要素を追加します scala> map("hello") = 1 // キーがworldで値が2の要素を追加します scala> map("world") = 2 // 構成されたMapはこんな感じです scala> map res31: scala.collection.mutable.Map[String,Int] = Map(hello -> 1, world -> 2) // Mapの要素にアクセスします scala> map("hello") res32: Int = 1
ミュータブルMapを使った基本操作はこんな感じですねー
Mapを使ったサンプル
Mapを使ったもう少し複雑なサンプルをやってみますかね、先程Setでやったサンプルに似たようなもので、文章の中の単語がそれぞれ幾つずつ含まれているか数える処理を書いてみますよ
// 今回もミュータブル版Mapを使いますよ scala> import scala.collection.mutable import scala.collection.mutable // いい加減極まりない文章を定義しますよ scala> val text = "Hello World is worldwide in hello world!" text: java.lang.String = Hello World is worldwide in hello world! // 空にミュータブルMapを定義します scala> val counts = mutable.Map.empty[String, Int] counts: scala.collection.mutable.Map[String,Int] = Map() // 文章を区切り文字で単語に分解してカウントアップしますよ scala> for(rawWord <- text.split("[ ,.!]+")){ // 単語を小文字にします | val word = rawWord.toLowerCase // カウントアップ元の数字を取り出しますよ | val oldCount = { // もし該当単語がMapに登録されていればその数字を | if (counts.contains(word)) counts(word) // なければ0を返します | else 0 | } // 数字を1加えてMapに値を格納します | counts += (word -> (oldCount + 1)) | } // 構成されたMapです scala> counts res36: scala.collection.mutable.Map[String,Int] = Map(hello -> 2, worldwide -> 1, world -> 2, is -> 1, in -> 1)
Mapの操作
Setと同様にMapについても記法操作をズラズラと乗っけますよ
//// イミュータブル編 // マップを構築しますよ scala> val numMap = Map("i"->1, "ii"->2) numMap: scala.collection.immutable.Map[java.lang.String,Int] = Map(i -> 1, ii -> 2) // マップに要素を追加します scala> numMap + ("vi"->6) res37: scala.collection.immutable.Map[java.lang.String,Int] = Map(i -> 1, ii -> 2, vi -> 6) // マップから要素を取り除きます scala> numMap - "ii" res38: scala.collection.immutable.Map[java.lang.String,Int] = Map(i -> 1) // マップに複数要素を追加しますよ scala> numMap ++ List("iii"->3, "v"->5) res39: scala.collection.immutable.Map[java.lang.String,Int] = Map(i -> 1, ii -> 2, iii -> 3, v -> 5) // マップから複数要素を取り除きますよ scala> numMap -- List("i", "ii") res40: scala.collection.immutable.Map[java.lang.String,Int] = Map() // Mapの要素数を取得します scala> numMap.size res41: Int = 2 // Mapの要素の存在チェックをします scala> numMap.contains("ii") res42: Boolean = true // Mapの要素を指定して取り出します scala> numMap("ii") res43: Int = 2 // マップのキーで構成されたIteratorを生成します scala> numMap.keys res44: Iterator[java.lang.String] = non-empty iterator // イテレータを使ってみますよー scala> val numMapIt = numMap.keys numMapIt: Iterator[java.lang.String] = non-empty iterator // 次の要素が存在します scala> numMapIt.hasNext res45: Boolean = true // 次の要素を取得します scala> numMapIt.next res46: java.lang.String = i // Mapのキー全体をSetとして取得します scala> numMap.keySet res47: scala.collection.Set[java.lang.String] = Set(i, ii) // Mapの値で構成されたIteratorを生成します scala> numMap.values res48: Iterator[Int] = non-empty iterator // イテレーターってみます scala> val numMapIt = numMap.values numMapIt: Iterator[Int] = non-empty iterator // 次の要素の存在チェックです scala> numMapIt.hasNext res49: Boolean = true // 次の要素を取り出しますよ scala> numMapIt.next res50: Int = 1 // Mapの空チェックをします scala> numMap.isEmpty res51: Boolean = false //// ミュータブル編です scala> import scala.collection.mutable import scala.collection.mutable // 空のミュータブルMapを生成します scala> val wordMap = mutable.Map.empty[String, Int] wordMap: scala.collection.mutable.Map[String,Int] = Map() // Mapの値を追加します scala> wordMap += ("one"->1) // 追加結果です scala> wordMap res58: scala.collection.mutable.Map[String,Int] = Map(one -> 1) // Mapから値を取り除きます scala> wordMap -= "one" // 結果ですよー scala> wordMap res60: scala.collection.mutable.Map[String,Int] = Map() // Mapに複数の値を追加してみますよ scala> wordMap ++= List("one"->1, "two"->2, "three"->3) scala> wordMap res62: scala.collection.mutable.Map[String,Int] = Map(one -> 1, two -> 2, three -> 3) // Mapから複数の値を取り除きますよ scala> wordMap --= List("one","two") scala> wordMap res64: scala.collection.mutable.Map[String,Int] = Map(three -> 3) // Mapの要素を全て取り除きますよー scala> wordMap.clear scala> wordMap res66: scala.collection.mutable.Map[String,Int] = Map()