String Scala:通过模式匹配拆分字符串

String Scala:通过模式匹配拆分字符串,string,scala,split,functional-programming,pattern-matching,String,Scala,Split,Functional Programming,Pattern Matching,有没有可能像这样将字符串拆分成lexems "user@domain.com" match { case name :: "@" :: domain :: "." :: zone => doSmth(name, domain, zone) } 换句话说,与列表的方式相同……是的,您可以使用Scala的功能来实现这一点 我找到了一个,如果这不适合您,请随意使用另一个: [-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+\.[a-zA-Z]{2,4} 我们要做的第一

有没有可能像这样将字符串拆分成lexems

"user@domain.com" match {
    case name :: "@" :: domain :: "." :: zone => doSmth(name, domain, zone)
}

换句话说,与列表的方式相同……

是的,您可以使用Scala的功能来实现这一点

我找到了一个,如果这不适合您,请随意使用另一个:

[-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+\.[a-zA-Z]{2,4}
我们要做的第一件事是在组周围添加括号:

([-0-9a-zA-Z.+_]+)@([-0-9a-zA-Z.+_]+)\.([a-zA-Z]{2,4})
我们有三组:在
@
之前的部分,在
@
之间的部分,最后是TLD

现在我们可以从中创建一个Scala正则表达式,然后使用Scala从绑定到变量的正则表达式中获取组:

val Email = """([-0-9a-zA-Z.+_]+)@([-0-9a-zA-Z.+_]+)\.([a-zA-Z]{2,4})""".r
Email: scala.util.matching.Regex = ([-0-9a-zA-Z.+_]+)@([-0-9a-zA-Z.+_]+)\.([a-zA-Z]    {2,4})


"user@domain.com" match {
    case Email(name, domain, zone) =>
       println(name)
       println(domain)
       println(zone)
}

// user
// domain
// com

一般来说,regex效率极低,所以我不建议这样做

您可以使用Scala模式匹配,通过调用字符串上的.toList将其转换为List[Char]。然后您的部分
名称
区域
也将被列表[Char],以将它们转换回字符串use.mkString。虽然我不确定这有多有效

我已经对各种用例使用基本字符串操作(如substring、indexOf等)进行了基准测试,与regex相比,regex通常慢一到两个数量级。当然,正则表达式是可怕的不可食


更新:最好使用解析器,无论是原生Scala解析器还是Parboiled2,从Scala 2.13开始,可以通过以下方式对字符串进行模式匹配:


如果您希望输入格式不正确,还可以使用匹配语句:

"user@domain.com" match {
  case s"$user@$domain.$zone" => Some(user, domain, zone)
  case _                      => None
}
// Option[(String, String, String)] = Some(("user", "domain", "com"))

+1这是我见过的语言处理正则表达式的最好方法之一。在许多语言中,这比另一种方法要好得多,迫使您手动访问
groups
对象,并通过索引或名称找到正确的匹配项。回答得好。我不确定你是否能做到,但我可以解释为什么你的例子不起作用。本质上,您拥有的是字符串列表的匹配器,因为,又名“cons”操作符,用元素构建列表。您需要的是一个case类,它接受两个列表并将它们连接起来,很像
操作符(但不幸的是,与cons不同,没有
case类)。什么?你每次都在重建正则表达式吗?正则表达式的要点是,它们创建的“机器”可以非常有效地匹配字符串。此外,将正则表达式用于非常小的检查是没有意义的,但对于更复杂的匹配,我希望能大大节省效率,特别是当通过的输入数量增加时。@KenoguLabz不,正则表达式的构造超出了基准。当我上次参加Scala eXchange会议时,我看到一篇演讲,声称使用解析器(或本机Scala
StringOps
)通常要快100到1000倍。显然,如果正则表达式构建得很糟糕,那么速度差可能会更大(查找回溯)。我自己的基准测试通常是在由数十亿条记录组成的真实数据上执行的。@samthebest我对此非常感兴趣,因为我发现正则表达式作为一种语言是无法维护的。如何优于编译的正则表达式自动机?你对此有多确定,或者你能详细说明什么情况?赤裸裸的
StringOps
当然级别太低,无法用。。。不太可能是一个好的选择,因为在这些情况下,一个特定的方法适合您的小的特殊需要。是否需要在此和/或在回答中详细说明?@matt使用解析器的三个主要好处是:(a)可以选择使用正则表达式风格的语法或全名版本,例如
zeroOrMore
+
,这可以提高可读性;(b)静态完整键入,例如
+
提供一个
列表,然后可以映射、转换等,这也意味着IDE将在语法上突出显示它(c)parboiled2是基于部分宏的,并且经过编译,因此可以大大快于正则表达式。谢谢,对我来说,这些优势一开始就很明显。但我发现这些可以解决速度方面的问题:。要是他们能被信任就好了,就像我记得看到人们说“煮咖啡”很慢一样。
"user@domain.com" match {
  case s"$user@$domain.$zone" => Some(user, domain, zone)
  case _                      => None
}
// Option[(String, String, String)] = Some(("user", "domain", "com"))