【问题标题】:Scala regex on a whole column整列上的 Scala 正则表达式
【发布时间】:2022-01-22 02:13:17
【问题描述】:

我有以下模式,我可以在 Python 中使用 pandas 进行解析,但很难将代码翻译成 Scala。

grade string_column    
 85   (str:ann smith,14)(str:frank chase,15)
 86   (str:john foo,15)(str:al more,14)

在我使用的python中:

df.set_index('grade')['string_column']\
.str.extractall(r'\((str:[^,]+),(\d+)\)')\
.droplevel(1)

输出:

 grade       0                1
 85      str:ann smith       14
 85      str:frank chase     15
 86      str:john foo        15
 86      str:al more         14

在 Scala 中,我尝试复制该方法,但失败了:

import scala.util.matching.Regex

val pattern = new Regex("((str:[^,]+),(\d+)\)")
val str = "(str:ann smith,14)(str:frank chase,15)"

println(pattern findAllIn(str)).mkString(","))

【问题讨论】:

    标签: regex scala


    【解决方案1】:

    代码有几点说明:

    • 组有一个不匹配的括号,但应该转义该括号
    • 反斜杠应该双转义
    • println 中,您不必使用所有括号和点
    • findAllIn 返回一个 MatchIterator,循环它们会暴露一个匹配的字符串。用逗号连接那些匹配的字符串,在这种情况下会再次返回相同的字符串。

    例如

    import scala.util.matching.Regex
    
    val pattern = new Regex("\\((str:[^,]+),(\\d+)\\)")
    val str = "(str:ann smith,14)(str:frank chase,15)"
    
    println(pattern findAllIn str mkString ",")
    

    输出

    (str:ann smith,14),(str:frank chase,15)
    

    但是如果你想打印出第 1 组和第 2 组的值,你可以使用返回 Regex Matches 集合的findAllMatchIn

    import scala.util.matching.Regex
    
    val pattern = new Regex("\\((str:[^,]+),(\\d+)\\)")
    val str = "(str:ann smith,14)(str:frank chase,15)"
    pattern findAllMatchIn str foreach(m => {
        println(m.group(1))
        println(m.group(2))
      }
    )
    

    输出

    str:ann smith
    14
    str:frank chase
    15
    

    【讨论】:

      【解决方案2】:

      在 Python 中,Series.str.extractall 仅返回捕获的子字符串。在 Scala 中,如果您不查询其 matchData 属性,而 findAllIn 又包含 subgroups 属性,则 findAllIn 将返回匹配的值。

      因此,要仅在 Scala 中获取捕获,您需要使用

      val pattern = """\((str:[^,()]+),(\d+)\)""".r
      val str = "(str:ann smith,14)(str:frank chase,15)"
      (pattern findAllIn str).matchData foreach {
          m => println(m.subgroups.mkString(","))
      }
      

      输出:

      str:ann smith,14
      str:frank chase,15
      

      请参阅Scala online demo

      在这里,m.subgroups 访问每个匹配 (m) 的所有子组(捕获)。

      另外,请注意您不需要在三引号字符串文字中使用双反斜杠。 \((str:[^,()]+),(\d+)\) 匹配

      • \( - 一个 ( 字符
      • (str:[^,()]+) - 第 1 组:str: 和一个或多个除 ,() 之外的字符
      • , - 逗号
      • (\d+) - 第 2 组:一位或多位数字
      • \) - 一个 ) 字符。

      如果您只想获取所有匹配项而不捕获,您可以使用

      val pattern = """\((str:[^,]+),(\d+)\)""".r
      println((pattern findAllIn str).matchData.mkString(","))
      

      输出:

      (str:ann smith,14),(str:frank chase,15)
      

      请参阅online demo

      【讨论】:

      • 谢谢。我需要如何调整代码以在新数据帧(如 pandas)中获取输出?
      猜你喜欢
      • 2013-09-19
      • 1970-01-01
      • 2013-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-26
      • 1970-01-01
      • 2015-06-19
      相关资源
      最近更新 更多