我有一个配对的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个元素,上述解决方案将变得很丑陋。
答案 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) }
相当于您自己的示例。