diff --git a/algebird-test/src/test/scala/com/twitter/algebird/TupleAggregatorsTest.scala b/algebird-test/src/test/scala/com/twitter/algebird/TupleAggregatorsTest.scala index 422f3ec05..fcaf2d466 100644 --- a/algebird-test/src/test/scala/com/twitter/algebird/TupleAggregatorsTest.scala +++ b/algebird-test/src/test/scala/com/twitter/algebird/TupleAggregatorsTest.scala @@ -340,6 +340,13 @@ class TupleAggregatorsTest extends WordSpec with Matchers { val MinLongAgg = Aggregator.min[Int].andThenPresent{ _.toLong } + "Create an aggregator from 1 (key, aggregator) pair" in { + val agg: Aggregator[Int, Long, Map[String, Long]] = MapAggregator( + ("key1", SizeAgg)) + val expectedMap = Map("key1" -> 6) + assert(agg(data) == expectedMap) + } + "Create an aggregator from 2 (key, aggregator) pairs" in { val agg: Aggregator[Int, Tuple2[Int, Long], Map[String, Long]] = MapAggregator( ("key1", MinLongAgg), diff --git a/project/GenTupleAggregators.scala b/project/GenTupleAggregators.scala index 1e75fdcee..4ed979859 100644 --- a/project/GenTupleAggregators.scala +++ b/project/GenTupleAggregators.scala @@ -66,8 +66,17 @@ object MapAggregator { } def genMapMethods(max: Int, isMonoid: Boolean = false): String = { + val aggType = if (isMonoid) "Monoid" else "" + + // there's no Semigroup[Tuple1[T]], so just use T as intermediary type instead of Tuple1[T] + val aggregatorForOneItem = s""" + |def apply[K, A, B, C](aggDef: (K, ${aggType}Aggregator[A, B, C])): ${aggType}Aggregator[A, B, Map[K, C]] = { + | val (key, agg) = aggDef + | agg.andThenPresent(value => Map(key -> value)) + |} + """.stripMargin + (2 to max).map(i => { - val aggType = if (isMonoid) "Monoid" else "" val nums = (1 to i) val bs = nums.map("B" + _).mkString(", ") val aggs = nums.map(x => "agg%s: Tuple2[K, %sAggregator[A, B%s, C]]".format(x, aggType, x)).mkString(", ") @@ -90,6 +99,6 @@ def apply[K, A, %s, C](%s): %sAggregator[A, %s, Map[K, C]] = { prepares, semiType, semigroup, tupleBs, present) - }).mkString("\n") + }).mkString("\n") + aggregatorForOneItem } }