Scalaを使ってみる: (1) ファイルからの入力
Scalaを勉強している.勉強中の身ではあるが,以下を例題として,Scalaプログラムの作り方について説明してみる.
与えられたテキストファイル中に現れる英単語の出現回数を数えて,出現回数の多い英単語から表示する.入力のテキストファイルとしては,Project Gutenberg 中のHalmet を用いる(ファイル名を hamlet.txt,改行はLFにした).
なお利用している環境は,Ubuntu 8.04 LTS上の Scala 2.8.0 RC2 (2010年5月10日リリース), Java 1.6.0である.
scala.io.Source
ここでは,すべての処理を iterative に行うことを目指す.
なぜ iterative に処理をするかといえば,無駄なメモリ消費をしないためである.たとえば,入力ファイルの全体を一つのListにすると,入力ファイルサイズに比例するメモリ量を必要とするが, iterative に処理をすれば,必要に応じて要求駆動(on-demand)でファイルからデータを読み込まれ,不要となったデータはゴミ集め(garbage collection)で回収されることが期待できるため,無駄なメモリ消費を避けることが可能になる.
入力を iterative に処理するにはscala.io.Source を用いる.
以下のようにすると,入力ファイルの各文字に対するscala.collection.Iteratorが得られる.
scala> io.Source.fromPath("hamlet.txt")
scala.io.Source = non-empty iterator
- 2010年11月29日追記: Scala 2.8.1 では io.Source.fromFile である.
文字毎のIteratorだと不便なので,getLinesを用いて行毎のIteratorにする.
scala> io.Source.fromPath("hamlet.txt").getLines() Iterator[String] = non-empty iterator
sizeで行数がわかるし, take(n)で最初のn行を取り出して,toListでリストにできる.
scala> io.Source.fromPath("hamlet.txt").getLines().size Int = 7067 scala> io.Source.fromPath("hamlet.txt").getLines().take(2).toList List[String] = List(Project Gutenberg Etext of Hamlet by Shakespeare, PG has multiple editions of William Shakespeare's Complete Works)
filterとfilterNotメソッド
filterで述語を満たす行だけを抽出することができ, filterNotで述語を満たす行を取り除くことができる.
たとえば,filterNotの述語として「s => s.matches("\\s*")」あるいは「_.matches("\\s*")」を指定すれば,空行を取り除くことになる.
scala> io.Source.fromPath("hamlet.txt").getLines(). | filterNot(_.matches("\\s*")).size Int = 5537
以上をまとめて関数getLinesとして定義しておく.
scala> def getLines(f: String) = | io.Source.fromPath(f).getLines().filterNot(_.matches("\\s*")) getLines: (f: String)Iterator[String] scala> getLines("hamlet.txt").take(2).toList List[String] = List(Project Gutenberg Etext of Hamlet by Shakespeare, PG has multiple editions of William Shakespeare's Complete Works)
「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回)