spark rdd,需要减少(key,(tuple))

时间:2017-09-27 13:34:10

标签: scala apache-spark rdd

之前的过程以下一种方式给了我累加器和每个组的计数:

val data: Array[(Int, (Double, Int))] = Array((2,(2.1463120403829962,7340)), (1,(1.4532644653720025,4280)))

结构为(groupId,(acum,count))

现在想减少以获得每个元组的总和:

(k1,(a1,n1)),(k2,(a2,n2))

需要:

(a1+a2),(n1+n2)

听起来像一个简单的任务,所以:

val mainMean = groups.reduce((acc,v)=>(acc._1 + v._1,acc._2 + v._2))

得到:

  

:33:错误:类型不匹配;发现:( Double,Int)   必需:字符串          val mainMean = groups.reduce((acc,v)=>(acc._1 + v._1,acc._2 + v._2))

也尝试过:

val mainMean = groups.reduce((k,(acc,v))=>(acc._1 + v._1,acc._2 + v._2))

告诉我:注意:元组不能在方法或函数参数中直接解构。       创建一个接受Tuple2的参数,       或考虑匹配匿名函数的模式

所以:

val mainMean = groups.reduce({case(k,(acc,n))=>(k,(acc._1+n._1,acc._1+n._2))})    

并获取

  

错误:类型不匹配;发现:(Int,(Double,Int))必需:Int

我知道这是一个新手问题,但我被困在上面

1 个答案:

答案 0 :(得分:1)

使用元组可能会遇到一些困难。
下面你可以看到工作代码,但让我解释一下。

val data = Array((2,(2.1463120403829962,7340)), (1,(1.4532644653720025,4280)))

def tupleSum(t1: (Int, (Double, Int)), t2: (Int, (Double, Int))): (Int, (Double, Int)) =
    (0,(t1._2._1 + t2._2._1, t1._2._2 + t2._2._2))

val mainMean = data.reduce(tupleSum)._2

我们可以引入reduce个参数,例如

data.reduce((tuple1, tuple2) => tupleSum(tuple1, tuple2))

其中tuple1是一种累加器。在第一次迭代时,它获取数组的第一个值,并且每个下一个值都会添加到accumulator的值。

因此,如果您想使用模式匹配执行reduce,它将如下所示:

val mainMean = data.reduce((tuple1, tuple2) => { 
  val t1 = tuple1 match { case (i, t) => t }
  val t2 = tuple2 match { case (i, t) => t }
// now t1 and t2 represents inner tuples of input tuples
  (0, (t1._1 + t2._1, t1._2 + t2._2))}
)


UPD。 我重写了以前的列表添加类型注释和println语句。我希望这有助于明白这一点。之后有一些解释。

val data = Array((3, (3.0, 3)), (2,(2.0,2)), (1,(1.0,1)))

val mainMean = data.reduce((tuple1: (Int, (Double, Int)),
                             tuple2: (Int, (Double, Int))) => {
    println("tuple1: " + tuple1)
    println("tuple2: " + tuple2)

    val t1: (Double, Int) = tuple1 match {
        case (i: Int, t: (Double, Int)) => t
    }
    val t2: (Double, Int) = tuple2 match {
        case (i: Int, t: (Double, Int)) => t
    }
    // now t1 and t2 represents inner tuples of input tuples
    (0, (t1._1 + t2._1, t1._2 + t2._2))}
)
println("mainMean: " + mainMean)

输出将是:

tuple1: (3,(3.0,3)) // 1st element of the array
tuple2: (2,(2.0,2)) // 2nd element of the array
tuple1: (0,(5.0,5)) // sum of 1st and 2nd elements
tuple2: (1,(1.0,1)) // 3d element
mainMean: (0,(6.0,6)) // result sum


tuple1tuple2类型为(Int, (Double, Int))。我们知道它总是只有这种类型,这就是我们在模式匹配中只使用一种情况的原因。我们将tuple1解压缩到i: Intt: (Int, Double)。只要我们对密钥不感兴趣,我们只返回t。现在t1代表tuple1的内部元组。与tuple2t2相同的故事。

您可以找到有关折叠函数herehere

的更多信息