Scala使用reduce时出现类型不匹配错误,求排查代码问题
问题分析与解决方案
这个错误的根源是对reduce方法的使用误解——reduce要求传入的函数必须接收两个和集合元素同类型的参数,并且返回相同类型的值,但你的代码里_.x + _.x返回的是Double,而集合元素是Point,类型不匹配,所以触发了类型错误。
修正方案1:用map+sum(最简洁直观)
我们可以先把每个Point映射成它的x/y坐标,再直接用sum方法求和,这是最符合语义的写法:
case class Point(x: Double, y: Double) def centroid(points: IndexedSeq[Point]): Point = { val sumX = points.map(_.x).sum val sumY = points.map(_.y).sum val len = points.length Point(sumX / len, sumY / len) }
修正方案2:用foldLeft一次遍历求和
如果想只遍历集合一次(性能上的微小优化,大多数场景下没必要),可以用foldLeft同时累积x和y的总和:
case class Point(x: Double, y: Double) def centroid(points: IndexedSeq[Point]): Point = { val (sumX, sumY) = points.foldLeft((0.0, 0.0)) { case ((accX, accY), point) => (accX + point.x, accY + point.y) } val len = points.length Point(sumX / len, sumY / len) }
为什么原来的reduce不行?
再强调一下:reduce的函数签名是(A, A) => A,它的输入和输出必须都是集合的元素类型(这里是Point)。如果非要用reduce,你得写一个把两个Point合并成一个新Point的函数,比如:
// 这只是演示reduce的正确用法,不适合求质心 points.reduce((p1, p2) => Point(p1.x + p2.x, p1.y + p2.y))
但这样得到的是所有Point坐标相加后的Point,后续再除以长度也能得到质心,但显然不如前面两种方法简洁清晰。
内容的提问来源于stack exchange,提问作者3va
相关产品推荐
相关产品推荐

