模式匹配 - Spark Scala RDD

4

我是从R语言背景转到Spark和Scala的新手。在对RDD进行一些转换之后,我得到了一个类型为

Description: RDD[(String, Int)]

现在我想在String RDD上应用正则表达式,从字符串中提取子字符串并将子字符串仅添加到新列中。
输入数据:
BMW 1er Model,278
MINI Cooper Model,248

我需要的输出结果:

   Input                  |  Brand   | Series      
BMW 1er Model,278,          BMW ,        1er        
MINI Cooper Model ,248      MINI ,      Cooper

品牌和系列是从字符串RDD中新计算出的子字符串。

目前为止,我已经使用正则表达式对一个字符串进行了操作,但是我不能将其应用于所有行。

 val brandRegEx = """^.*[Bb][Mm][Ww]+|.[Mm][Ii][Nn][Ii]+.*$""".r //to look for BMW or MINI

那么我可以使用

brandRegEx.findFirstIn("hello this mini is bmW testing")

但是我该如何对RDD的所有行使用它,并应用不同的正则表达式以实现上述输出呢?

我阅读了这个代码片段,但不确定如何将其整合在一起。

val brandRegEx = """^.*[Bb][Mm][Ww]+|.[Mm][Ii][Nn][Ii]+.*$""".r

def getBrand(Col4: String) : String = Col4 match {
    case brandRegEx(str)  =>  
    case _ => ""
    return 'substring
}

任何帮助都将不胜感激!
谢谢。

1
可以详细说明这里的问题是什么吗?是关于正则表达式、模式匹配还是RDD转换? - zero323
@zero323:如果问题不清晰,请见谅。基本上,我想在Spark-scala RDD中使用正则表达式进行字符串匹配。 - user3560220
2个回答

8

要将正则表达式应用于 RDD 中的每个项,您应该使用 RDD 的 map 函数,该函数使用某些函数(在本例中为部分函数)转换 RDD 中的每一行,以提取构成每一行的元组的两个部分:

import org.apache.spark.{SparkContext, SparkConf}

object Example extends App {

  val sc = new SparkContext(new SparkConf().setMaster("local").setAppName("Example"))

  val data = Seq(
    ("BMW 1er Model",278),
    ("MINI Cooper Model",248))

  val dataRDD = sc.parallelize(data)

  val processedRDD = dataRDD.map{
    case (inString, inInt) =>
      val brandRegEx = """^.*[Bb][Mm][Ww]+|.[Mm][Ii][Nn][Ii]+.*$""".r
      val brand = brandRegEx.findFirstIn(inString)
      //val seriesRegEx = ...
      //val series = seriesRegEx.findFirstIn(inString)
      val series = "foo"
      (inString, inInt, brand, series)
  }

  processedRDD.collect().foreach(println)
  sc.stop()
}

请注意,我认为您的正则表达式存在一些问题,您还需要一个用于查找系列的正则表达式。此代码输出:
(BMW 1er Model,278,BMW,foo)
(MINI Cooper Model,248,NOT FOUND,foo)

如果你根据自己的需求调整了正则表达式,那么你可以按照以下步骤将它们应用到每一行。


谢谢您的快速回复。我也采用了同样的方法,但是我发现我的正则表达式有问题。我会尝试去纠正它并在这里发布我的解决方案。 - user3560220
使用 findFirstIn(inString) 我无法仅获取我需要的子字符串。例如:如果我的输入字符串是 Model BMW 5seriesfindFirstIn(inString) 还会返回前缀 "Model BMW",请问应该使用哪个函数?显然,findFirstIn 不会给出仅为子字符串的结果。 - user3560220
看看我的示例代码,它确实提取了子字符串,例如“BMW”。还要注意,“Model BMW”实际上是一个子字符串,只是不是你想要的子字符串。问题在于你的正则表达式不够具体。 - mattinbits

1

嗨,我只是在寻找另一个问题时看到了这个问题。可以使用常规转换来解决上述问题。

val a=sc.parallelize(collection)
a.map{case (x,y)=>(x.split (" ")(0)+" "+x.split(" ")(1))}.collect

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接