整列上的 Scala 正则表达式

Posted

技术标签:

【中文标题】整列上的 Scala 正则表达式【英文标题】:Scala regex on a whole column 【发布时间】: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(","))

【问题讨论】:

【参考方案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)中获取输出?

以上是关于整列上的 Scala 正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

在 df 列上迭代不同的正则表达式模式

怎样在scala正则表达式提取器中使用小括号

Scala快速入门--正则对象

Scala正则和抽取器:解析方法参数

从零学scala文件和正则表达式特质

scala正则表达式