繁体   English   中英

如何使用Spark的地图转换在Scala中返回多个键值对?

[英]How do I return multiple key-value pairs in Scala using Spark's map transformation?

我是Scala和Spark的新手。 我试图在地图转换期间返回多个键值对。 我的输入数据是一个简单的CSV文件。

1, 2, 3
4, 5, 6
7, 8, 9

我的Scala脚本如下所示。

class Key(_i:Integer, _j:Integer) {
 def i = _i
 def j = _j
}
class Val(_x:Double, _y:Double) {
 def x = _x
 def y = _y
}
val arr = "1,2,3".split(",")
for(i <- 0 until arr.length) {
 val x = arr(i).toDouble
 for(j <- 0 until arr.length) {
  val y = arr(j).toDouble
  val k = new Key(i, j)
  val v = new Val(x, y)
  //note that i want to return the tuples, (k, v)
 }
}

我希望能够使用上面的for循环和数据结构来返回多个元组(k,v)。 类似于下面的代码。

val file = sc.textFile("/path/to/test.csv")
file.map(line => {
 val arr = line.split(",")
 for(i <- 0 until arr.length) {
  val x = arr(i).toDouble
  for(j <- (i+1) until arr.length) {
   val y = arr(j).toDouble
   val k = new Index(i,j)
   val v = new Val(x,y)
   (k,v)
  }
 }
}).collect //reduceByKey is not there, reduce is there, but not what i want

当我将上面的代码复制/粘贴到lambda表达式(并在Scala REPL shell上运行)时,我收到以下错误:

error: illegal start of simple expression
val arr = line.split(",")
^

我也意识到我仍然处于命令式/程序式编程思维中,所以请耐心等待(以及Scala / Spark的新手)。

使用RDD.flatMapyield从列表中for循环:

val file = sc.textFile("/path/to/test.csv")
file.flatMap { line =>
  val arr = line.split(",")
  for {
    i <- 0 until arr.length
    j <- (i + 1) until arr.length
  } yield {
    val x = arr(i).toDouble
    val y = arr(j).toDouble
    val k = new Index(i, j)
    val v = new Val(x, y)
    (k, v)
  }
}.collect

你忘记了箭头后的方括号。 如果它是一个简单的表达式(一个表达式),则只能省略它们。

file.map(line => {
    //multiple lines of code here
})

编辑后的完整答案:

case class Index(i:Integer, j:Integer)
case class Val(x:Double, y:Double)

val data = sc.parallelize(List("1,2,3", "4,5,6", "7,8,9"))
data.flatMap(line=>{
val arr = line.split(",")
 val doubleSeq = for(i <- 0 until arr.length) yield {
  val x = arr(i).toDouble
  for(j <- (i+1) until arr.length) yield {
   val y = arr(j).toDouble
   val k = Index(i,j)
   val v = Val(x,y)
   (k,v)
  }
 }
 doubleSeq.flatten
})

实际上有很多问题:

  • 请注意,我将类更改为case类,因为它们是可序列化的。 否则,您将需要实现Serializable
  • 我将map更改为flatMap ,并将数组flatten因为一个flatMap仍会留下内部数组。 现在,两者的组合将产生你的RDD[(Index, Val)] ,现在可以隐式地与reduceByKey一起reduceByKey
  • 我通过使用yield将你的for循环转换为for comprehension。 你得到的是最终类型的Unit因为for循环的返回类型是Unit

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM