[英]reduce variable number of tuples Sequences to Map[Key, List[Value]] in Scala
[英]Scala - Reduce list of tuples by key
我有一个包含userId
和point
的元组列表。 我想按键组合或缩小此列表。
val points: List[(Int, Double)] = List(
(1, 1.0),
(2, 3.2),
(4, 2.0),
(1, 4.0),
(2, 6.8)
)
预期结果应如下所示:
List((1, 5.0), (2, 10.0), (4, 2.0))
我尝试使用groupBy
和mapValue
,但出现错误:
val aggrPoint: Map[Int, Double] = incomes.groupBy(_._1).mapValues(seq => seq.reduce(_._2 + _._2))
Error:(16, 180) type mismatch;
found : Double
required: (Int, Double)
我在做什么错,有没有惯用的方式来做到这一点?
PS),我发现,在星火aggregateByKey
做这件工作。 但是,Scala中有内置方法吗?
您可以map
在元组mapValues
他们的第二个元素,然后sum
它们如下:
points.groupBy(_._1).mapValues( _.map(_._2).sum ).toList
// res1: List[(Int, Double)] = List((2,10.0), (4,2.0), (1,5.0))
我在做什么错,有没有惯用的方式来做到这一点?
让我们一步一步去看看你在做什么错 。 (我将使用REPL )
首先让我们定义点
scala> val points: List[(Int, Double)] = List(
| (1, 1.0),
| (2, 3.2),
| (4, 2.0),
| (1, 4.0),
| (2, 6.8)
| )
points: List[(Int, Double)] = List((1,1.0), (2,3.2), (4,2.0), (1,4.0), (2,6.8))
如您所见,您具有List[Tuple2[Int, Double]]
因此当您将groupBy
和mapValues
做为
scala> points.groupBy(_._1).mapValues(seq => println(seq))
List((2,3.2), (2,6.8))
List((4,2.0))
List((1,1.0), (1,4.0))
res1: scala.collection.immutable.Map[Int,Unit] = Map(2 -> (), 4 -> (), 1 -> ())
您可以再次看到seq
对象是List[Tuple2[Int, Double]]
, 但只包含成组的tuple作为list 。
因此,当您应用seq.reduce(_._2 + _._2)
, reduce
函数接受Tuple2[Int, Double]
两个输入,但输出仅为Double
,与预期的seq
上的下一次迭代不匹配输入是Tuple2[Int, Double
] 。 多数民众赞成在主要问题 。 您所需要做的就是匹配输入和输出类型,以reduce
功能
一种方法是将Tuple2[Int, Double]
匹配为
scala> points.groupBy(_._1).mapValues(seq => seq.reduce{(x,y) => (x._1, x._2 + y._2)})
res6: scala.collection.immutable.Map[Int,(Int, Double)] = Map(2 -> (2,10.0), 4 -> (4,2.0), 1 -> (1,5.0))
但这不是您想要的输出,因此您可以从简化的Tuple2[Int, Double]
提取double值Tuple2[Int, Double]
如下所示:
scala> points.groupBy(_._1).mapValues(seq => seq.reduce{(x,y) => (x._1, x._2 + y._2)}._2)
res8: scala.collection.immutable.Map[Int,Double] = Map(2 -> 10.0, 4 -> 2.0, 1 -> 5.0)
或者您可以在应用reduce
功能之前使用map
scala> points.groupBy(_._1).mapValues(seq => seq.map(_._2).reduce(_ + _))
res3: scala.collection.immutable.Map[Int,Double] = Map(2 -> 10.0, 4 -> 2.0, 1 -> 5.0)
我希望解释清楚清楚,可以理解您的错误,并且您必须已经了解了reduce
函数的工作原理
使用collect
points.groupBy(_._1).collect{
case e => e._1 -> e._2.map(_._2).sum
}.toList
//res1: List[(Int, Double)] = List((2,10.0), (4,2.0), (1,5.0))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.