我正在尝试实现一个从字符串中提取“占位符”列表的函数。起始占位符和结束占位符的分隔符为$。我有一些想法如何使用var启用/禁用累积来实现它,我想做的就是在没有任何var的情况下实现它
对于像这样的字符串
val stringToParse = "ignore/me/$aaa$/once-again/ignore/me/$bbb$/still-to-be/ignored
结果应该是
Seq("aaa", "bbb")
有什么提示吗?
这是使用var的解决方案
import fiddle.Fiddle, Fiddle.println
import scalajs.js
import scala.collection.mutable.ListBuffer
@js.annotation.JSExportTopLevel("ScalaFiddle")
object ScalaFiddle {
// $FiddleStart
val stringToParse = "ignore/me/$aaa$/once-again/ignore/me/$bbb$/still-to-be/ignored"
class StringAccumulator {
val accumulator: ListBuffer[String] = new ListBuffer[String]
val sb: StringBuilder = new StringBuilder("")
var open:Boolean = false
def next():Unit = {
if (open) {
accumulator.append(sb.toString)
sb.clear
open = false
} else {
open = true
}
}
def accumulateIfOpen(charToAccumulate: Char):Unit = {
if (open) sb.append(charToAccumulate)
}
def get(): Seq[String] = accumulator.toList
}
def getPlaceHolders(str: String): Seq[String] = {
val sac = new StringAccumulator
str.foreach(chr => {
if (chr == '$') {
sac.next()
} else {
sac.accumulateIfOpen(chr)
}
})
sac.get
}
println(getPlaceHolders(stringToParse))
// $FiddleEnd
}
答案 0 :(得分:1)
这个解决方案够吗?
node->key
答案 1 :(得分:1)
我将向您介绍两种解决方案。首先是您所做的最直接的翻译。在Scala中,如果您听到单词accumulate
,通常会翻译成fold
或reduce
的变体。
def
extractValues(s: String) =
{
//We can combine the functionality of your boolean and stringbuilder by using an Option
s.foldLeft[(ListBuffer[String],Option[StringBuilder])]((new ListBuffer[String], Option.empty))
{
//As we fold through, we have the accumulated list, possibly a partially built String, and the current letter
case ((accumulator,sbOption),char) =>
{
char match
{
//This logic pretty much matches what you had, adjusted to work with the Option
case '$' =>
{
sbOption match
{
case Some(sb) =>
{
accumulator.append(sb.mkString)
(accumulator,None)
}
case None =>
{
(accumulator,Some(new StringBuilder))
}
}
}
case _ =>
{
sbOption.foreach(_.append(char))
(accumulator,sbOption)
}
}
}
}._1.map(_.mkString).toList
}
但是,这似乎很复杂,因为听起来像是一个简单的任务。我们可以使用正则表达式,但是它们很吓人,因此请避免使用它们。实际上,经过一点思考,这个问题实际上变得非常简单。
def extractValuesSimple(s: String)=
{
s.split('$').//split the string on the $ character
dropRight(1).//Drops the rightmost item, to handle the case with an odd number of $
zipWithIndex.filter{case (str, index) => index % 2 == 1}.//Filter out all of the even indexed items, which will always be outside of the matching $
map{case (str, index) => str}.toList//Remove the indexes from the output
}