2017-02-06 7 views
0

例は非常にエレガントです:リフト地図

scala> Map(1 -> Max(2)) + Map(1 -> Max(3)) + Map(2 -> Max(4)) 
res0: Map[Int,Max[Int]] = Map(2 -> Max(4), 1 -> Max(3)) 

は基本的に、ここで地図の使用は、SQLのgroup byと同等です。

しかし、私は任意のアグリゲータでこれをどうやって行うのですか?例えば、上記の(しかしMaxラッパークラスなし)コードと同じことを達成するために

scala> import com.twitter.algebird._ 
scala> val mx = Aggregator.max[Int] 
mx: Aggregator[Int,Int,Int] = MaxAggregator([email protected]) 
scala> val mxOfMap = // what goes here? 
mxOfMap: Aggregator[Map[Int,Int],Map[Int,Int],Map[Int,Int]] = ... 
scala> mxOfMap.reduce(List(Map(1 -> 2), Map(1 -> 3), Map(2 -> 4))) 
res0: Map[Int,Int] = Map(2 -> 4, 1 -> 3) 

言い換えれば、どのようにIは、変換(または「リフト」)型の値で動作するアグリゲータ(任意のKの場合)の値で動作するアグリゲータに、Tを挿入しますか?

答えて

0

これはかなり簡単にSemigroupのために行うことができますように見えます。これは、保存する必要のあるアグリゲータの「構成」または「現在」のフェーズに追加のロジックがない場合に十分です(からSemigroupを取得し、compose/prepareを破棄してください)。

元の質問に答えるためのコードは次のとおりです。

scala> val sgOfMap = Semigroup.mapSemigroup[Int,Int](mx.semigroup) 
scala> val mxOfMap = Aggregator.fromSemigroup(sgOfMap) 
scala> mxOfMap.reduce(List(Map(1 -> 2), Map(1 -> 3), Map(2 -> 4))) 
res0: Map[Int,Int] = Map(2 -> 4, 1 -> 3) 

しかし、実際には、直接、任意Semigroupを構築するのではなく、から半群を抽出するために、単にAggregatorを構築することにより開始する方が良いだろう。

scala> import com.twitter.algebird._ 
scala> val mx = Semigroup.from { (x: Int, y: Int) => Math.max(x, y) } 
scala> val mxOfMap = Semigroup.mapSemigroup[Int,Int](mx) 
scala> mxOfMap.sumOption(List(Map(1 -> 2), Map(1 -> 3), Map(2 -> 4))) 
res33: Option[Map[Int,Int]] = Some(Map(2 -> 4, 1 -> 3)) 

あるいは、アグリゲータに変換:Aggregator.fromSemigroup(mxOfMap)