Scalaを使ってみる: (2) 英単語の抽出
Scalaを勉強している.勉強中の身ではあるが,以下を例題として,Scalaプログラムの作り方について説明してみる.
テキストファイル中に現れる英単語の出現回数を数えて,出現回数の多い語から表示する.入力のテキストファイルとしては,Project Gutenberg 中のHalmet を用いる(ファイル名を hamlet.txt,改行はLFにした).
なお利用している環境は,Ubuntu 8.04 LTS上の Scala 2.8.0 RC2 (2010年5月10日リリース), Java 1.6.0である.
正規表現 (Regex)
各行の文字列を英単語毎に分解するには,正規表現のクラスscala.util.matching.Regex を用いる.
たとえば「"[a-zA-Z]+".r」が英単語にマッチする正規表現である.
scala> "[a-zA-Z]+".r
scala.util.matching.Regex = [a-zA-Z]+
findAllInで,正規表現にマッチする文字列のIteratorが返ってくる.
scala> "[a-zA-Z]+".r.findAllIn("Hamlet, Prince of Denmark") scala.util.matching.Regex.MatchIterator = non-empty iterator scala> "[a-zA-Z]+".r.findAllIn("Hamlet, Prince of Denmark").toList List[String] = List(Hamlet, Prince, of, Denmark)
なお正規表現として「"\\p{InCJK_UNIFIED_IDEOGRAPHS}+".r」を用いれば,漢字にマッチする文字列を抽出できる.
mapメソッド
mapで,各要素に関数を適用できる.
たとえば,以下のようにするとリスト中の各文字列の文字を小文字に変換できる.
scala> List("Hamlet", "Prince", "of", "Denmark").map(_.toLowerCase) List[String] = List(hamlet, prince, of, denmark)
文字列から英単語を抽出する関数
Regexとmapを用いて,与えられた文字列から英単語をIteratorとして抽出する関数toWordsを定義する.
scala> def toWords(s: String) = "[a-zA-Z]+".r.findAllIn(s).map(_.toLowerCase) toWords: (s: String)Iterator[java.lang.String] scala> toWords("Hamlet, Prince of Denmark") Iterator[java.lang.String] = non-empty iterator scala> toWords("Hamlet, Prince of Denmark").toList List[java.lang.String] = List(hamlet, prince, of, denmark)
flatMapメソッド
入力ファイルの各行に,上のtoWordsを適用すれば良いのだが, mapを用いるとIteratorのIteratorになる.
scala> getLines("hamlet.txt").map(toWords) Iterator[Iterator[java.lang.String]] = non-empty iterator
Iteratorを統合し,一つのIteratorにまとめるにはflatMapを用いる.
scala> getLines("hamlet.txt").flatMap(toWords) Iterator[java.lang.String] = non-empty iterator scala> getLines("hamlet.txt").flatMap(toWords).size Int = 34743 scala> getLines("hamlet.txt").flatMap(toWords).take(5).toList List[java.lang.String] = List(project, gutenberg, etext, of, hamlet)
「Scalaを使ってみる」の目次
- (1) ファイルからの入力
- (2) 英単語の抽出
- (3) 出現回数を数える (mutable版)
- (4) Mapのメソッド
- (5) プログラム作成 (mutable版)
- (6) MultiSetを定義する (mutable版)
- (7) immutable MultiSetを定義する
- (8) immutable MultiSetのメソッドを定義する
- (9) immutable MultiSetのメソッドを高速化する
- (10) immutable MultiSetのメソッドを高速化する (続き)
- (11) immutable MultiSetのメソッドをリファクタリング
- (12) Martin Oderskyによるオンライン授業
- (13) Martin Oderskyによるオンライン授業 (第2回)