Scala:如何使用多个分隔符进行拆分



我想知道如何使用 Scala 使用多个分隔符拆分字符串。

例如,如果我有一个分隔符列表:

List("Car", "Red", "Boo", "Foo")

还有一根要收获的绳子:

Car foerjfpoekrfopekf Red ezokdpzkdpoedkzopke dekpzodk Foo azdkpodkzed

我希望能够输出类似的东西:

List(   ("Car", " foerjfpoekrfopekf "),
    ("Red", " ezokdpzkdpoedkzopke dekpzodk "),
    ("Foo", " azdkpodkzed")     
)

您可以使用该列表创建正则表达式并使用其拆分方法:

val regex = List("Car", "Red", "Boo", "Foo").mkString("|").r
regex.split("Car foerjfpoekrfopekf Red ezokdpzkdpoedkzopke dekpzodk Foo azdkpodkzed")

但是,这并不能告诉您在哪里使用了哪个分隔符。如果你需要它,我建议你尝试Scala的解析器库。

编辑:

或者,您可以使用正则表达式一次提取一对,如下所示:

def split(s:String, l:List[String]):List[(String,String)] = {
  val delimRegex = l.mkString("|")
  val r = "("+delimRegex+")(.*?)(("+delimRegex+").*)?"
  val R = r.r
  s match {
    case R(delim, text, rest, _) => (delim, text) :: split(rest, l)
    case _ => Nil
  }
}

有点冗长,但它有效:
弃用版本:(它有一个错误,把它留在这里,因为你已经接受了答案)

def f(s: String, l: List[String], g: (String, List[String]) => Int) = {
    for {
        t <- l
        if (s.contains(t))
        w = s.drop(s.indexOf(t) + t.length)
    } yield (t, w.dropRight(w.length - g(w, l)))
}
def h(s: String, x: String) = if (s.contains(x)) s.indexOf(x) else s.length
def g(s: String, l: List[String]): Int = l match {
    case Nil => s.length
    case x :: xs => math.min(h(s, x), g(s, xs))
}
val l = List("Car", "Red", "Boo", "Foo")
val s = "Car foerjfpoekrfopekf Red ezokdpzkdpoedkzopke dekpzodk Foo azdkpodkzed"

输出:

f(s, l, g).foreach(println)
> (Car, foerjfpoekrfopekf )
> (Red, ezokdpzkdpoedkzopke dekpzodk )
> (Foo, azdkpodkzed)

它返回Array[String]而不是列表。 但你也可以这样做: f(s, l, g).toList

编辑:刚刚注意到,如果分隔符在字符串中只出现一次,则此代码很好。如果定义s如下:

val s = "Car foerjfpoekrfopekf Red ezokdpzkdpoedkzopke dekpzodk Foo azdkpodkzed Car more..."

我仍然会得到相同的结果,而不是另一对("Car"," more...")

编辑#2:无错误版本 这是固定的代码片段:

def h(s: String, x: String) = if (s.contains(x)) s.indexOf(x) else s.length
def multiSplit(str: String, delimiters: List[String]): List[(String, String)] = {
    val del = nextDelimiter(str, delimiters)
    del._1 match {
        case None => Nil
        case Some(x) => {
            val tmp = str.drop(x.length)
            val current = tmp.dropRight(tmp.length - nextDelIndex(tmp,delimiters))
            (x, current) :: multiSplit(str.drop(x.length + current.length), delimiters)
        }
    }
}
def nextDelIndex(s: String, l: List[String]): Int = l match {
    case Nil => s.length
    case x :: xs => math.min(h(s, x), nextDelIndex(s, xs))
}
def nextDelimiter(str: String, delimiters: List[String]): (Option[String], Int) = delimiters match {
    case Nil => (None, -1)
    case x :: xs => {
        val next = nextDelimiter(str, xs)
        if (str.contains(x)) {
            val i = str.indexOf(x)
            next._1 match {
                case None => (Some(x), i)
                case _ => if (next._2 < i) next else (Some(x), i)
            }
        } else next
    }
}

输出:

multiSplit(s, l).foreach(println)
> (Car, foerjfpoekrfopekf )
> (Red, ezokdpzkdpoedkzopke dekpzodk )
> (Foo, azdkpodkzed)
> (Car, more...)

现在它可以:)

最新更新