- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我刚刚开始使用Scala,希望更好地了解解决问题的功能方法。
我有成对的字符串,第一个具有用于参数的占位符,而这对具有可替换的值。例如
“从tab1中选择col1,其中id> $ 1,名称类似$ 2”
“参数:$ 1 ='250',$ 2 ='some%'”
可能有两个以上的参数。
我可以通过在每行上逐步使用regex.findAllIn(line)并然后通过迭代器来构造替换来构建正确的字符串,但这似乎相当不雅且由程序驱动。
谁能指出我要一种更整洁,更不易出错的功能性方法?
最佳答案
严格说来替换问题,我的首选解决方案是通过一项功能启用的解决方案,该功能可能会在即将到来的Scala 2.8中提供,该功能可以使用功能替换正则表达式模式。使用它,问题可以简化为:
def replaceRegex(input: String, values: IndexedSeq[String]) =
"""\$(\d+)""".r.replaceAllMatchesIn(input, {
case Regex.Groups(index) => values(index.toInt)
})
"select col1 from tab1 where id > %1$s and name like %2$s" format ("one", "two")
(String, List[String]) => String
(String, IndexedSeq[String]) => String
(String, Pattern) => String
val stringPattern = "\\$(\\d+)"
val regexPattern = stringPattern.r
def replaceRecursive(input: String, values: IndexedSeq[String]): String = regexPattern findFirstIn input match {
case regexPattern(index) => replaceRecursive(input replaceFirst (stringPattern, values(index.toInt)))
case _ => input // no placeholder found, finished
}
StringBuilder
。我们还希望避免创建新的字符串。
StringBuilder
可以接受
CharSequence
,我们可以从
String
获得。我不确定是否实际创建了新字符串-如果是,我们可以以查看
CharSequence
的方式滚动自己的
String
而不是创建新的
String
。确保我们可以根据需要轻松更改此设置,我将假设不是。
String => Int
(String, Int) => Int
(String, Int) => Option[Int]
def indexOfPlaceholder(input: String, start: Int): Option[Int] = if (start < input.lengt) {
input indexOf ("$", start) match {
case -1 => None
case index =>
if (index + 1 < input.length && input(index + 1).isDigit)
Some(index)
else
indexOfPlaceholder(input, index + 1)
}
} else {
None
}
(String, Int) => Int
:
def placeholderLength(input: String, start: Int): Int = {
def recurse(pos: Int): Int = if (pos < input.length && input(pos).isDigit)
recurse(pos + 1)
else
pos
recurse(start + 1) - start // start + 1 skips the "$" sign
}
(String, Int) => Int
Int
是输入的索引,而第二个是值的索引。我们可以对此做些事情,但不能那么容易或有效地做,所以让我们忽略它。这是一个实现:
def indexOfValue(input: String, start: Int): Int = {
def recurse(pos: Int, acc: Int): Int = if (pos < input.length && input(pos).isDigit)
recurse(pos + 1, acc * 10 + input(pos).asDigit)
else
acc
recurse(start + 1, 0) // start + 1 skips "$"
}
def indexOfValue2(input: String, start: Int, length: Int): Int = if (length > 0) {
input(start + length - 1).asDigit + 10 * indexOfValue2(input, start, length - 1)
} else {
0
}
replaceRecursive
所需的一切:
def replaceRecursive2(input: String, values: IndexedSeq[String]): String = {
val sb = new StringBuilder(input.length)
def recurse(start: Int): String = if (start < input.length) {
indexOfPlaceholder(input, start) match {
case Some(placeholderIndex) =>
val placeholderLength = placeholderLength(input, placeholderIndex)
sb.append(input subSequence (start, placeholderIndex))
sb.append(values(indexOfValue(input, placeholderIndex)))
recurse(start + placeholderIndex + placeholderLength)
case None => sb.toString
}
} else {
sb.toString
}
recurse(0)
}
StringBuilder
效率更高,功能也一样。
T[A]
的情况下将
T[B]
转换为
A => B
,这被称为函子。谈到收藏时,很容易理解。例如,我可以通过函数
List[String]
将名称的
List[Int]
转换为名称长度的
String => Int
,该函数返回字符串的长度。那是一个列表理解。
A => T[B]
的功能,这些功能还可以通过理解来完成,这些功能与monad或
A => Boolean
有关。
T[A]
。我们不能使用
Array[Char]
作为输入,因为我们要替换整个占位符,该占位符大于单个char。因此,让我们提出这种类型的签名:
(List[String], String => String) => String
String
,因此我们首先需要一个函数
String => List[String]
,它将我们的输入分为占位符和非占位符。我建议:
val regexPattern2 = """((?:[^$]+|\$(?!\d))+)|(\$\d+)""".r
def tokenize(input: String): List[String] = regexPattern2.findAllIn(input).toList
IndexedSeq[String]
,但是我们需要一个
String => String
。有很多解决方法,但让我们解决一下:
def valuesMatcher(values: IndexedSeq[String]): String => String = (input: String) => values(input.substring(1).toInt - 1)
List[String] => String
,但是
List
的
mkString
已经做到了。因此,几乎没有什么可以做的所有这些东西组成:
def comprehension(input: List[String], matcher: String => String) =
for (token <- input) yield (token: @unchecked) match {
case regexPattern2(_, placeholder: String) => matcher(placeholder)
case regexPattern2(other: String, _) => other
}
@unchecked
是因为如果我的正则表达式模式正确构建,则除了上述两种模式之外,不应有其他模式。但是,编译器并不知道这一点,因此我使用该注释来使它产生的警告静音。如果引发异常,则正则表达式模式中存在错误。
def replaceComprehension(input: String, values: IndexedSeq[String]) =
comprehension(tokenize(input), valuesMatcher(values)).mkString
List
是不必要的中间结果。我们可以通过以下更改解决此问题:
def tokenize2(input: String): Iterator[List[String]] = regexPattern2.findAllIn(input).matchData.map(_.subgroups)
def comprehension2(input: Iterator[List[String]], matcher: String => String) =
for (token <- input) yield (token: @unchecked) match {
case List(_, placeholder: String) => matcher(placeholder)
case List(other: String, _) => other
}
def replaceComprehension2(input: String, values: IndexedSeq[String]) =
comprehension2(tokenize2(input), valuesMatcher(values)).mkString
T[A]
输入,一个
B
“种子”和一个函数
(B, A) => B
。我们使用函数来理解列表,始终使用最后处理的元素产生的
B
(第一个元素获取种子)。最后,我们返回最后一个被理解元素的结果。
def factorial(n: Int) = {
val input = 2 to n
val seed = 1
val function = (b: Int, a: Int) => b * a
input.foldLeft(seed)(function)
}
def factorial2(n: Int) = (2 to n).foldLeft(1)(_ * _)
tokenize2
的结果作为可理解的输入,并执行以下操作:
def replaceFolding(input: String, values: IndexedSeq[String]) = {
val seed = new StringBuilder(input.length)
val matcher = valuesMatcher(values)
val foldingFunction = (sb: StringBuilder, token: List[String]) => {
token match {
case List(_, placeholder: String) => sb.append(matcher(placeholder))
case List(other: String, _) => sb.append(other)
}
sb
}
tokenize2(input).foldLeft(seed)(foldingFunction).toString
}
StringBuilder
,因为
String
的连接很慢。如果不是这种情况,我可以轻松地用
StringBuilder
替换上面函数中的
String
。我还可以将
Iterator
转换为
Stream
,并完全消除可变性。
关于scala - 用Scala中的占位符替换字符串中的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2183503/
我有一些 Scala 代码,它用两个不同版本的类型参数化函数做了一些漂亮的事情。我已经从我的应用程序中简化了很多,但最后我的代码充满了形式 w(f[Int],f[Double]) 的调用。哪里w()是
如果我在同一目录中有两个单独的未编译的 scala 文件: // hello.scala object hello { def world() = println("hello world") }
val schema = df.schema val x = df.flatMap(r => (0 until schema.length).map { idx => ((idx, r.g
环境: Play 2.3.0/Scala 2.11.1/IntelliJ 13.1 我使用 Typesafe Activator 1.2.1 用 Scala 2.11.1 创建一个新项目。项目创建好后
我只是想知道如何使用我自己的类扩展 Scala 控制台和“脚本”运行程序,以便我可以通过使用实际的 Scala 语言与其通信来实际使用我的代码?我应将 jar 放在哪里,以便无需临时配置即可从每个 S
我已经根据 README.md 文件安装了 ensime,但是,我在低级 ensime-server 缓冲区中出现以下错误: 信息: fatal error :scala.tools.nsc.Miss
我正在阅读《Scala 编程》一书。在书中,它说“一个函数文字被编译成一个类,当在运行时实例化时它是一个函数值”。并且它提到“函数值是对象,因此您可以根据需要将它们存储在变量中”。 所以我尝试检查函数
我有 hello world scala native 应用程序,想对此应用程序运行小型 scala 测试我使用通常的测试命令,但它抛出异常: NativeMain.scala object Nati
有few resources在网络上,在编写与代码模式匹配的 Scala 编译器插件方面很有指导意义,但这些对生成代码(构建符号树)没有帮助。我应该从哪里开始弄清楚如何做到这一点? (如果有比手动构建
我是 Scala 的新手。但是,我用 创建了一个中等大小的程序。斯卡拉 2.9.0 .现在我想使用一个仅适用于 的开源库斯卡拉 2.7.7 . 是吗可能 在我的 Scala 2.9.0 程序中使用这个
有没有办法在 Scala 2.11 中使用 scala-pickling? 我在 sonatype 存储库中尝试了唯一的 scala-pickling_2.11 工件,但它似乎不起作用。我收到消息:
这与命令行编译器选项无关。如何以编程方式获取代码内的 Scala 版本? 或者,Eclipse Scala 插件 v2 在哪里存储 scalac 的路径? 最佳答案 这无需访问 scala-compi
我正在阅读《Scala 编程》一书,并在第 6 章中的类 Rational 实现中遇到了一些问题。 这是我的 Rational 类的初始版本(基于本书) class Rational(numerato
我是 Scala 新手,我正在尝试开发一个使用自定义库的小项目。我在库内创建了一个mysql连接池。这是我的库的build.sbt organization := "com.learn" name :
我正在尝试运行一些 Scala 代码,只是暂时打印出“Hello”,但我希望在 SBT 项目中编译 Scala 代码之前运行 Scala 代码。我发现在 build.sbt 中有以下工作。 compi
Here链接到 maven Scala 插件使用。但没有提到它使用的究竟是什么 Scala 版本。我创建了具有以下配置的 Maven Scala 项目: org.scala-tools
我对 Scala 还很陌生,请多多包涵。我有一堆包裹在一个大数组中的 future 。 future 已经完成了查看几 TB 数据的辛勤工作,在我的应用程序结束时,我想总结上述 future 的所有结
我有一个 scala 宏,它依赖于通过包含其位置的静态字符串指定的任意 xml 文件。 def myMacro(path: String) = macro myMacroImpl def myMacr
这是我的功能: def sumOfSquaresOfOdd(in: Seq[Int]): Int = { in.filter(_%2==1).map(_*_).reduce(_+_) } 为什么我
这个问题在这里已经有了答案: Calculating the difference between two Java date instances (45 个答案) 关闭 5 年前。 所以我有一个这
我是一名优秀的程序员,十分优秀!