3va
3va

Reputation: 85

type mismatch in scala when using reduce

Can anybody help me understand what's wrong with the code below?

case class Point(x: Double, y: Double)

def centroid(points: IndexedSeq[Point]): Point = {
  val x = points.reduce(_.x + _.x)
  val y = points.reduce(_.y + _.y)
  val len = points.length
  Point(x/len, y/len)
}

I get the error when I run it:

Error:(10, 30) type mismatch;
 found   : Double
 required: A$A145.this.Point
  val x = points.reduce(_.x + _.x)
                            ^

Upvotes: 0

Views: 480

Answers (2)

Tim
Tim

Reputation: 27356

If you want to use reduce you need to reduce both x and y in a single pass like this

def centroid(points: IndexedSeq[Point]): Point = {
  val p = points.reduce( (s, p) => Point(s.x + p.x, s.y + p.y) )
  val len = points.length

  Point(p.x/len, p.y/len)
}

If you want to compute x and y independently then use foldLeft rather than reduce like this

def centroid(points: IndexedSeq[Point]): Point = {
  val x = points.foldLeft(0.0)(_ + _.x)
  val y = points.foldLeft(0.0)(_ + _.y)
  val len = points.length

  Point(x/len, y/len)
}

This is perhaps clearer but does process the points twice so it may be marginally less efficient.

Upvotes: 1

Jeffrey Chung
Jeffrey Chung

Reputation: 19517

reduce, in this case, takes a function of type (Point, Point) => Point and returns a Point.

One way to calculate the centroid:

case class Point(x: Double, y: Double)

def centroid(points: IndexedSeq[Point]): Point = {
  val x = points.map(_.x).sum
  val y = points.map(_.y).sum
  val len = points.length
  Point(x/len, y/len)
}

Upvotes: 1

Related Questions