【问题标题】:Is Haskell-style pattern matching on Scala Strings possible?Scala 字符串上的 Haskell 样式模式匹配是否可行?
【发布时间】:2019-01-25 15:15:59
【问题描述】:

我只是好奇。

我尝试使用 Haskell 方式在 Scala 中进行模式匹配字符串(作为字符列表)

例如,这个函数删除字符串中的第一个“/”字符:

import scala.language.implicitConversions

implicit def stringToChars(s: String): List[Char] = s.toCharArray.toList

implicit def charsToString(a: List[Char]): String = a.mkString

def filterFirstSlash: Function[List[Char], String] = {
  case Nil => ""
  case '/' :: Nil => ""
  case '/' :: xs => xs
  case xs => xs
}

用法:

println(filterFirstSlash("/test"))

我可以使用模式匹配删除前导斜杠吗?这样做好不好?

更新

这将删除头部和尾部的所有条目:

def removeAllSlashes: Function[List[Char], String] = {
    case Nil => ""
    case '/' :: xs => removeAllSlashes(xs)
    case xs :+ '/' => removeAllSlashes(xs)
    case xs => xs
}

这将只删除第一个条目:

def removeFirstSlash: Function[List[Char], String] = {
    case Nil => ""
    case ('/' :: xs) :+ '/' => xs
    case '/' :: xs => xs
    case xs :+ '/' => xs
    case xs => xs
}

附言 不要那么认真。 这只是为了好玩。 感谢参与讨论的所有人。

【问题讨论】:

  • 也许你可以使用replaceFirst并通过正则表达式^\\/..也看看这里stackoverflow.com/questions/21545933/…
  • @WiktorStribiżew 我回滚了,抱歉。如果您添加 [regex] 标签,我可能会同意,因为在这种情况下,这似乎是一种合适的解决方案。但我反对删除pattern-matching,因为“为什么模式匹配在这里不起作用”似乎是问题的重要部分。
  • 我知道正则表达式。这不是关于它。我的好奇心是 - 有可能以haskell方式做吗? :)

标签: scala pattern-matching


【解决方案1】:

不,这不是一个好方法。 Strings 不是字符列表。在 JVM 上,字符串是 UTF-16 代码单元的不可变数组。它们与链表无关。您的 filterFirstSlash 将始终忽略前三种情况,并始终返回未更改的输入。

要删除斜线,您可以执行以下操作:

"////abcd".dropWhile(_ == '/')  // returns `"abcd"`

"/abcd".replaceAll("^/", "")

((s: String) => if (s startsWith "/") s.tail else s )("/abcd")

或者,如果您真的坚持模式匹配,那么您可以使用预编译的正则表达式模式来匹配前导斜杠和字符串的其余部分:

val Rgx = "^/(.*)$".r
"/abcd" match { case Rgx(s) => s; case s => s }      // evaluates to `"abcd"`

【讨论】:

  • @HoTicE 然后我强烈建议您在 repl 中尝试一下:"abcd".tail == "bcd"。它只是删除第一个字符。与s.substring(1)相同。
  • @airudah 什么“这个”? dropWhile?它将删除所有前导斜杠。我假设最多有一个。如果最多删除一个斜线至关重要,那么其他三个解决方案可以做到这一点。
  • 也许我理解错了,但我认为他希望删除尾部的第一个 /,而不是每个 /..
  • @airudah 您不必推测:只需使用函数def filterFirstSlash = (s: String) => s.toList match { case Nil => ""; case '/' :: xs => xs.mkString; case xs => xs.mkString } 并在几个示例中尝试它的作用,如果您没有直接从代码中看到它。
  • 不不,我知道它按设计工作......啊,没关系,这个问题有点令人困惑。我已经更正了措辞
【解决方案2】:

技术上是可能的:

def filterFirstSlash(s: String) = {
  case '/' +: xs => xs
  case xs => xs
}

当然,它不如链表的相同代码高效,因为+: 每次都复制整个字符串,所以你不想用它来递归地分离字符串。

【讨论】:

    猜你喜欢
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-11
    • 2018-03-15
    • 2016-11-12
    • 2012-09-17
    相关资源
    最近更新 更多