【问题标题】:Flatten value in paired RDD in sparkSpark中配对RDD中的展平值
【发布时间】:2018-10-11 05:01:18
【问题描述】:

我有一个配对的 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 个,则上述解决方案会变得很难看。

【问题讨论】:

  • 你的方法看起来不错。你有什么理由寻找替代品吗?
  • @RahulSharma。主要是好奇,因为我的方式看起来太“手动”了。如果value 包含超过 2 个元素(添加到问题中)怎么办?

标签: scala apache-spark rdd


【解决方案1】:

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

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

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

编辑: map { case ... } 模式非常紧凑,只要结构在编译时已知,就可以用于令人惊讶的深度嵌套元组。如果您在编译时绝对不能知道元组的结构,那么这里有一些 hacky、缓慢的代码,可能可以将任何嵌套的元组弄平......只要总共不超过 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)))

【讨论】:

    【解决方案2】:

    没有更好的方法。第一个答案相当于:

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

    相当于你自己的例子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-29
      • 2017-08-25
      • 1970-01-01
      • 2016-06-24
      • 1970-01-01
      • 2017-02-20
      • 1970-01-01
      相关资源
      最近更新 更多