LoginSignup
0
0

More than 5 years have passed since last update.

Scalaでスネークケースをキャメルケースに変換する方法

Posted at

概要

スネークケース(snake case)の文字列を、キャメルケース(lower camel case)に変換する方法をいくつか試してみました。
簡単のため、元の文字列はスネークケースとして well-formed であるとします。
(_foo bar_ B_aZ などの文字列は想定しない)

試した実装方法

Iteratorを使った命令型の方法

普通にIteratorでループして、 _ の場合はもう一文字読み込んで大文字にしています。
(注:文字列の末尾が _ だと落ちます)

  def byIte(str: String): String = {
    val it = str.iterator
    val sb = new StringBuilder
    while (it.hasNext) {
      val c = it.next()
      sb + ( if (c == '_') it.next().toUpper else c )
    }
    sb.toString()
  }

正規表現を使った方法

replaceAllIn を使って、 置換をかけます。

  private val Reg = """_([a-z0-9])""".r

  def byRegex(str: String): String = Reg.replaceAllIn(str, { m => m.group(1).toUpperCase } )

foldLeftを使った方法

こちらは、ググって見つけたいかにも関数型っぽい素敵なやり方です。
List は先頭への要素追加が高速なので、最後に reverse をかけて反転させています。
foldLeft の動きを理解していないと、よくわからないかもしれません。
タプルの1つ目はアキュムレータで、 List[Char] 型です。2つ目は個々の要素で Char 型です。

 def byFold(str: String): String = {
    str.toList.foldLeft(List.empty[Char]){
      case ('_'::xs, c) => c.toUpper::xs
      case (xs, c) => c::xs
    }.reverse.mkString
  }

zipを使った方法

大文字にするかどうかの判定にはひとつ前の文字が必要ということで、 List[Char] と、1文字シフトした List[Char]zip して、ひとつ前の文字とのタプルを使って判定してみたものです。

  def byZip(str: String): String = {
    val chars = str.toList
    val cs =
      for ((c1, c2) <- chars zip (' ' :: chars) if c1 != '_' )
        yield (c1, c2) match {
          case (c, '_') => c.toUpper
          case (c, _) => c
        }
    cs.mkString
  }

処理イメージは以下です。(※は読み飛ばし)

0 1 2 3 4 5 6
文字 f o o _ b a r
一つ前 f o o _ b a
結果 f o o B a r

パフォーマンス

各方法について、手元の環境で計測した結果の比較です。
"check_performance_of_snake_to_camel_conversion" という文字列を10万回変換した時間です。

方法 ミリ秒
Iterator 135
Regex 605
foldLeft 286
zip 367

やはり、正規表現が一番遅いですね。
Iteratorで回す方法が最速でした。

よりシンプルな実装方法や、高速な実装方法をご存知の方は是非コメントください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0