【问题标题】:How to extract a part of string in RDD?如何在RDD中提取部分字符串?
【发布时间】:2017-06-23 10:14:32
【问题描述】:

经过几次转换,这是我拥有的 RDD 的输出:

( z287570731_serv80i:7:175 , 5:Re )
( p286274731_serv80i:6:100 , 138 )
( t219420679_serv37i:2:50 , 5 )
( v290380588_serv81i:12:800 , 144:Jo )
( z292902510_serv83i:4:45 , 5:Re )

使用此数据作为输入 RDD,我想提取两个分号之间的值。

例如:

Input = ( z287570731_serv80i:7:175 , 5:Re )
Output = 7 (:7:)

这就是我正在尝试的方式

    val processedRDD = tid.map{ 
    case (inString, inInt) => 
      val RegEx = """.*:([\d.]+):.*""".r
      val table_level = RegEx.findFirstIn(inString)
    }

    processedRDD.collect().foreach(println)

这是我得到的输出:

()
()
()
()
()
()
()

Spark-way 怎么做?

【问题讨论】:

  • Jamie Zawinski 的这句话必须说:有些人在遇到问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。
  • 我是一般编程以及 Scala 和 Spark 的新手。请提出更好/更有效的解决方案。
  • 我会选择@shankar Koirala 的解决方案。
  • 你使用什么 Spark 版本?
  • 2.1.1 @ Jacek Laskowski

标签: scala apache-spark rdd


【解决方案1】:

这里的答案非常好,但我错过了一个我相信可以轻松击败所有答案的答案:) 这正是我喜欢 Scala 的原因 - 因为它的灵活性。

解决方案

scala> val solution = rdd.
  map { case (left, right) => left }.
  map(_.split(":")).
  map { case Array(_, takeMe, _) => takeMe }.
  collect
solution: Array[String] = Array(7, 6, 2, 12, 4)

相信该解决方案在可读性和理解性方面几乎无可匹敌。它只是说明它的作用(就像一首好诗)。

说明

以下是您的 RDD(得益于 Spark SQL 的Dataset.show,输出格式精美)。

scala> rdd.toDF.show(false)
+-------------------------+------+
|_1                       |_2    |
+-------------------------+------+
|z287570731_serv80i:7:175 |5:Re  |
|p286274731_serv80i:6:100 |138   |
|t219420679_serv37i:2:50  |5     |
|v290380588_serv81i:12:800|144:Jo|
|z292902510_serv83i:4:45  |5:Re  |
+-------------------------+------+

// Compare to this assembler-like way and you understand why you should use Spark SQL for this
scala> rdd.foreach(println)
(z287570731_serv80i:7:175,5:Re)
(p286274731_serv80i:6:100,138)
(t219420679_serv37i:2:50,5)
(v290380588_serv81i:12:800,144:Jo)
(z292902510_serv83i:4:45,5:Re)

第一步是删除右列。模式匹配 FTW!

scala> rdd.map { case (left, right) => left }.foreach(println)
z292902510_serv83i:4:45
t219420679_serv37i:2:50
v290380588_serv81i:12:800
p286274731_serv80i:6:100
z287570731_serv80i:7:175

使用临时 RDD,您使用 : 作为分隔符拆分字符串并取第二个单词。又是 Scala 的模式匹配 FTW!

val oneColumnOnly = rdd.map { case (left, right) => left }
scala> oneColumnOnly.
  map(_.split(":")).  // <-- split
  map { case Array(_, takeMe, _) => takeMe }. // <-- take the 2nd field
  foreach(println)
6
12
4
2
7

【讨论】:

    【解决方案2】:

    您也可以使用 DataFrames 和 SparkSQL 来做到这一点

    val rddToDf = rdd.toDF
    rddToDf.createOrReplacetempView("df")
    spark.sql("select substr(_1, instr(_1,':')+1, instr(substr(_1, instr(_1,':')+1), ':')-1) as f  from df").show //spark can be SparkSession or SQLContext
    

    【讨论】:

      【解决方案3】:

      如果这是一个固定模式,那么您可以将 rdd 中的第一个值拆分为

      rdd.map( row => row._1.split(":")(1))
      

      这给了[7 6 2 12 4]

      获取[:7: :6: :2: :12: :4:]

      rdd.map( ":" + row => row._1.split(":")(1) + ":")
      

      希望对你有帮助

      【讨论】:

      • 我可以从一个 RDD 中分别提取两个模式吗?
      • 就像我有一个字符串“Hello, World”。我把 """.*e([\d.]+)0.*""".r 和 """.*w([\d.]+)l.*""".r 放在一起单个语句。
      【解决方案4】:

      {} 为范围的复合表达式的值是范围本身的最后一个值。

      map 调用的模式匹配中的最后一行是 val table_level = ...,这是一个赋值并返回 () 类型的 Unit

      你不应该把它分配给任何东西,而是写出这样的表达式

      val processedRDD = tid.map{ 
        case (inString, inInt) => 
          val RegEx = """.*:([\d.]+):.*""".r
          RegEx.findFirstIn(inString)
      }
      

      【讨论】:

        【解决方案5】:

        如果总是这样,您可以在 : 上拆分元组的第一个元素,然后执行另一个 map 以获得所需的输出。

        val rdd = sc.parallelize(Array(( "z287570731_serv80i:7:175" , "5:Re" ),
              ( "p286274731_serv80i:6:100" , "138" ),
              ( "t219420679_serv37i:2:50" , "5" ),
              ( "v290380588_serv81i:12:800" , "144:Jo" ),
              ( "z292902510_serv83i:4:45" , "5:Re" ) ))
        val mapped = rdd.map( x => x._1.split(":")(1) ).map( x => ":"+x+":")
        mapped.collect()
        res1: Array[String] = Array(:7:, :6:, :2:, :12:, :4:)
        

        【讨论】:

        • 你不需要两张地图,不是吗?
        • 是的,没必要。一个就可以完成。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-05
        • 2021-02-21
        • 1970-01-01
        相关资源
        最近更新 更多