2012年12月14日金曜日

Scala Tips / Streamで採番(2)

Streamで採番では、Streamのfromメソッドを使って数値の連番による番号の採番を行いました。

場合によっては、採番する番号として「A00001」というような英数字と数字の組合せを取りたい場合があります。

このような場合は、カスタムでStreamを作ることになります。

といっても、これは簡単で以下のような再帰関数のイディオムを使います。

def nums(i: Int): Stream[String] = {
  "A%05d".format(i) #:: nums(i + 1)
}

使ってみる

それでは新しく作ったnums関数による採番用Streamを使ってみましょう。

採番した値の型はStringになるのNumberedNameを修正します。

case class NumberedName(name: String, number: String)

シーケンスに対して採番を行い値と採番した番号のTupleを返す関数は以下になります。Stream#fromの代わりにnums関数を使っています。

def f(names: Seq[String]): Seq[NumberedName] = {
  for ((n, c) <- names zip nums(1)) yield {
    NumberedName(n, c)
  }
}

実行

それでは実行してみましょう。

まずテスト用のListを定義します。

scala> val xs = List("a", "b", "c")
xs: List[java.lang.String] = List(a, b, c)

このListに対する関数fの実行結果は以下になります。

scala> f(xs)
res6: Seq[NumberedName] = List(NumberedName(a,A00001), NumberedName(b,A00002), NumberedName(c,A00003))

ごくごく簡単に使うことができますね。

ノート

再帰関数とStreamを使うことで、採番ロジックを関数として部品化することができました。この部品はSeqのzip関数でシーケンスと結びつけることができます。

こういった疎結合の関数部品を用意して、関数合成のテクニックで組合せて使うのが、関数型らしいプログラミングです。Streamの活用はそのような関数型プログラミングを行う上で重要なテクニックになっています。

諸元

  • Scala 2.9.2

0 件のコメント:

コメントを投稿