经过几次转换后,这就是我所拥有的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?
答案 0 :(得分:3)
这里非常好的答案,但我错过了一个我相信可以轻松击败他们的人:)这就是我喜欢Scala的原因 - 因为它的灵活性。 / p>
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' s 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
答案 1 :(得分: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
答案 2 :(得分:1)
如果这是一个固定的模式,你可以将第一个值从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) + ":")
希望这有帮助
答案 3 :(得分:0)
作为{}
作用域的复合表达式的值是作用域本身的最后一个值。
map
来电模式匹配的最后一行是val table_level = ...
,这是一项作业,并返回()
类型的Unit
。
你不应该把它分配给任何东西,而是写下像
这样的表达式val processedRDD = tid.map{
case (inString, inInt) =>
val RegEx = """.*:([\d.]+):.*""".r
RegEx.findFirstIn(inString)
}
答案 4 :(得分:0)
你可以在:
上分割元组的第一个元素,如果它总是那样,那就做另一个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:)