2017-09-27 11 views
0

スパーク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)) 

とget:

:33: error: type mismatch; found : (Double, Int) required: String 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))})  

error: type mismatch; found : (Int, (Double, Int)) required: Int

を取得しますその上に

+0

を 'reduceByKey((ACC、V)=>(acc._1 + v._1、acc._2 + v._2))に関する詳細な情報を見つけることができます'、今は、acumulatorsとすべてのグループのカウントを合計する必要があります、それは私が示したように2つのステップで行うことができますが、私は1つをしたい。 – user2232395

答えて

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 

我々はtuple1は、アキュムレータの一種である

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

ようreduce引数を導入することができます。最初の反復では、配列の最初の値をとり、次の値がすべてaccumulatorの値に加算されます。だから、

あなたはそれが次のようになります。パターンマッチングを使用して削減実行する場合:

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))です。私たちはそれが常にこのタイプだけであることを知っています。そのため、パターンマッチングでは1つのケースしか使用しません。tuple1をi: Intt: (Int, Double)に解凍します。私たちがキーに興味がない限り、我々はtだけを返します。今度はt1tuple1の内側タプルを表しています。同じ話はtuple2t2です。

あなたが倍に機能hereと、前のステップだったhere

+0

@ wopqwありがとうございました、まさに私が望んでいた、タプルの解凍の問題です、関数を持つソリューションは理解しやすいですが、パターンマッチングはより複雑です、あなたはこれのより詳細な説明を与えることができます。私はパターン無名関数と一致するいくつかの例を読んでいますが、ただ1つの例だけがあります。これはtの意味ですか? – user2232395

+0

@ user2232395、私は答えを更新しました。私はそれが今より明確になることを願っています。何かがぼやけているかどうかお気軽に。 – wopqw

関連する問題