火花中配对RDD中的值变平

时间:2018-10-10 17:13:49

标签: scala apache-spark rdd

我有一个配对的RDD,看起来像

(a1, (a2, a3))
(b1, (b2, b3))
...

我想将值展平以获得

(a1, a2, a3)
(b1, b2, b3)
...

当前我正在

rddData.map(x => (x._1, x._2._1, x._2._2))

是否有更好的转换方法?如果value包含许多元素而不是2个元素,上述解决方案将变得很丑陋。

2 个答案:

答案 0 :(得分:2)

当我试图避免元组操作附带的所有丑陋的下划线数字时,我喜欢使用大小写表示法:

rddData.map { case (a, (b, c)) => (a, b, c) }

您还可以给变量赋予有意义的名称,以使代码能够自我记录,并且使用大括号表示嵌套括号更少。

编辑: map {case ...}模式非常紧凑,只要在编译时就知道该结构,就可以将其用于深度嵌套的元组。如果您绝对肯定在编译时不知道元组的结构,那么这里有一些骇人的,缓慢的代码,很可能可以使任意嵌套的元组扁平化……只要总共不超过23个元素。它的工作方式是将元组的每个元素递归转换为列表,将其平面映射为单个列表,然后使用可怕的反射将列表转换回元组,如here所示。

def flatten(b:Product): List[Any] = { 
  b.productIterator.toList.flatMap {
    case x: Product => flatten(x)
    case y: Any => List(y)
  }
}

def toTuple[Any](as:List[Any]):Product = {
  val tupleClass = Class.forName("scala.Tuple" + as.size)
  tupleClass.getConstructors.apply(0).newInstance(as.map(_.asInstanceOf[AnyRef]):_*).asInstanceOf[Product]
}

rddData.map(t => toTuple(flatten(t)))

答案 1 :(得分:1)

没有更好的方法。第一个答案等同于:

val abc2 = xyz.map{ case (k, v) => (k, v._1, v._2) }

相当于您自己的示例。