Лучшее форматирование строк в Scala
со слишком большим количеством аргументов,String.format легко становится слишком запутанным. Есть ли более мощный способ форматирования строки. Вот так:
"This is #{number} string".format("number" -> 1)
или это невозможно из-за проблем с типом (format нужно было бы взять карту[String, Any], я предполагаю; не знаю, будет ли это хуже).
или это лучший способ сделать это так:
val number = 1
<plain>This is { number } string</plain> text
даже если это загрязняет пространство имен?
Edit:
пока простой сутенер может сделать во многих случаях, я также ищу что-то происходит в том же направлении, что и Python format() (см.: http://docs.python.org/release/3.1.2/library/string.html#formatstrings)
7 ответов:
в 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
Ну, если ваша единственная проблема заключается в том, чтобы сделать порядок параметров более гибким, это можно легко сделать:
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
вы можете легко реализовать более богатое форматирование самостоятельно (с подходом 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
Если вы используете 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 ))
вы также можете рассмотреть возможность использования шаблонного движка для действительно сложных и длинных строк. На макушке у меня есть Scalate, который реализует среди других ус шаблонизатор.
может быть излишним и потеря производительности для простых строк, но вы, кажется, находитесь в той области, где они начинают становиться реальными шаблонами.
Comments