【问题标题】:Lift algebird aggregator to consume (and return) Map提升 algebird 聚合器以消耗(并返回)地图
【发布时间】:2017-02-06 01:36:17
【问题描述】:

README 中的例子非常优雅:

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))

这里使用的Map基本上相当于SQL的group by

但是我如何对任意聚合器做同样的事情呢?例如,要实现与上面的代码相同的事情(但没有Max 包装类):

scala> import com.twitter.algebird._
scala> val mx = Aggregator.max[Int]
mx: Aggregator[Int,Int,Int] = MaxAggregator(scala.math.Ordering$Int$@78c77)
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)

换句话说,我如何将对T 类型的值进行操作的聚合器转换(或“提升”)为对Map[K,T] 类型的值进行操作的聚合器(对于某些任意K)?

【问题讨论】:

    标签: scala algebird


    【解决方案1】:

    看起来这对于Semigroup 来说至少可以很容易地完成。如果在聚合器的“撰写”或“当前”阶段没有需要保留的额外逻辑,这应该就足够了(可以从 Aggregator 获得 Semigroup,丢弃撰写/准备) .

    回答原问题的代码是:

    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)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-12
      • 1970-01-01
      • 2014-10-13
      • 2013-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-13
      相关资源
      最近更新 更多