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

时间:2014-01-16 19:36:23

标签: string scala split functional-programming pattern-matching

是否有可能将字符串拆分为lexems,如

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

换言之,以与列表相同的方式......

3 个答案:

答案 0 :(得分:20)

是的,您可以使用Scala的Regex功能执行此操作。

我找到了一个email regex on this site,如果这不适合你,可以随意使用另一个:

[-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的pattern matching unapply将正则表达式中的组绑定到变量:

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

答案 1 :(得分:4)

一般来说,正则表达式非常低效,所以不建议。

您可以使用Scala模式匹配,通过调用字符串上的.toList将其转换为List [Char]。然后,您的部分namedomainzone也将是List [Char],将它们重新转换为字符串使用.mkString。虽然我不确定这是多么有效。

我已经使用基本的字符串操作(如substring,indexOf等)进行基准测试,用于各种用例与正则表达式相比,正则表达式通常慢一两个。当然,正则表达式是不可思议的。

更新:最好的办法是使用Parsers,原生Scala或Parboiled2

答案 2 :(得分:1)

Scala 2.13开始,可以按unapplying a string interpolator模式匹配String s:

val s"$user@$domain.$zone" = "user@domain.com"
// user: String = "user"
// domain: String = "domain"
// zone: String = "com"

如果您期望输入格式错误,还可以使用match语句:

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