我有以下模式,我可以在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(","))
关于代码有一些注释:
- 组有一个不匹配的括号,但应该转义
- 反斜杠应为双转义
- 在
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 值,可以使用返回正则表达式匹配集合的 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
在 Python 中,Series.str.extractall
只返回捕获的子字符串。在 Scala 中,如果不查询其matchData
属性(而该属性又包含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 在线演示。
在这里,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)
请参阅在线演示。