web-dev-qa-db-ja.com

Scalaの文字列フォーマットの改善

引数が多すぎると、_String.format_は混乱しやすくなります。文字列をフォーマットするより強力な方法はありますか?そのようです:

_"This is #{number} string".format("number" -> 1)
_

または、タイプの問題のためにこれは不可能です(formatはMap [String、Any]を取る必要があります。これが事態を悪化させるかどうかはわかりません)。

または、次のようにそれを行うより良い方法です:

_val number = 1
<plain>This is { number } string</plain> text
_

名前空間を汚染していても?

編集:

多くの場合、単純なポンピングで行うことができますが、Pythonのformat()と同じ方向に進むものも探しています(参照: http://docs.python.org/release/ 3.1.2/library/string.html#formatstrings

55
Debilski

Scala 2.10では、 文字列補間 を使用できます。

val height = 1.9d
val name = "James"
println(f"$name%s is $height%2.2f meters tall")  // James is 1.90 meters tall
71
Andrej Herich

さて、あなたの唯一の問題がパラメータの順序をより柔軟にすることである場合、これは簡単に行うことができます:

scala> "%d %d" format (1, 2)
res0: String = 1 2

scala> "%2$d %1$d" format (1, 2)
res1: String = 2 1

また、マップを使用した正規表現の置換もあります。

scala> val map = Map("number" -> 1)
map: scala.collection.immutable.Map[Java.lang.String,Int] = Map((number,1))

scala> val getGroup = (_: scala.util.matching.Regex.Match) group 1
getGroup: (util.matching.Regex.Match) => String = <function1>

scala> val pf = getGroup andThen map.lift andThen (_ map (_.toString))
pf: (util.matching.Regex.Match) => Option[Java.lang.String] = <function1>

scala> val pat = "#\\{([^}]*)\\}".r
pat: scala.util.matching.Regex = #\{([^}]*)\}

scala> pat replaceSomeIn ("This is #{number} string", pf)
res43: String = This is 1 string
38

Scala-Enhanced-Strings-Pluginが役立つかもしれません。ここを見て:

Scala-Enhanced-Strings-Plugin Documentation

17
Ruediger Keller

リッチなフォーマットを自分で簡単に実装できます(pimp-my-libraryアプローチを使用):

scala> implicit def RichFormatter(string: String) = new {
     |   def richFormat(replacement: Map[String, Any]) =
     |     (string /: replacement) {(res, entry) => res.replaceAll("#\\{%s\\}".format(entry._1), entry._2.toString)}
     | }
RichFormatter: (string: String)Java.lang.Object{def richFormat(replacement: Map[String,Any]): String}

scala> "This is #{number} string" richFormat Map("number" -> 1)
res43: String = This is 1 string
14
Vasil Remeniuk

これは私がここに来て探していた答えです:

"This is %s string".format(1)
9
Priyank Desai

2.10を使用している場合は、組み込み補間を使用します。それ以外の場合、極端なパフォーマンスを気にせず、機能的なワンライナーを恐れない場合は、fold +いくつかの正規表現スキャンを使用できます。

val template = "Hello #{name}!"
val replacements = Map( "name" -> "Aldo" )
replacements.foldLeft(template)((s:String, x:(String,String)) => ( "#\\{" + x._1 + "\\}" ).r.replaceAllIn( s, x._2 ))
4
Aldo Bucchi

また、本当に複雑で長い文字列に対してテンプレートエンジンの使用を検討することもできます。頭の上に Scalate があります。これは Mustache テンプレートエンジンを実装しています。

単純な文字列では過剰になり、パフォーマンスが低下する場合がありますが、実際のテンプレートになり始める領域にいるようです。

2
Dominik Bucher