Tesseract
Tesseract

Reputation: 8139

Alternative to List.sliding?

I'm trying to get more familiar with functional programming and I was wondering if there is a more elegant way to group a list into pairs of 2 and apply a function to those pairs.

case class Line(start: Vector, end: Vector) {
  def isLeftOf(v: Vector) = (end - start).cross(v - start) < 0
}

case class Polygon(vertices: List[Vector]) {
  def edges = (vertices.sliding(2).toList :+ List(vertices.last,vertices.head)).map(l => Line(l(0), l(1)))
  def contains(v: Vector) = {
    edges.map(_.isLeftOf(v)).forall(_ == true)
  }
}

I'm talking about this line

def edges = (vertices.sliding(2).toList :+ List(vertices.last,vertices.head)).map(l => Line(l(0), l(1)))

Is there a better way to write this?

Upvotes: 1

Views: 841

Answers (2)

Luigi Plinge
Luigi Plinge

Reputation: 51109

val edges = (vertices, vertices.tail :+ vertices.head).zipped map Line

See also these questions:

How do you turn a Scala list into pairs?

Most concise way to combine sequence elements

Upvotes: 2

dhg
dhg

Reputation: 52701

Well you can simplify a bit by doing this:

case class Polygon(vertices: List[Vector]) {
  def edges = Line(vertices.last, vertices.head) :: vertices.sliding(2).map(l => Line(l(0), l(1))).toList
  def contains(v: Vector) = edges.forall(_.isLeftOf(v))
}

I've done three things:

  1. Pulled the last/head Line out so that it isn't part of the map
  2. Moved toList to after map so that you map over an Iterator, saving you from constructing two Lists.
  3. Simplified contains to simply call forall with the predicate.

Upvotes: 0

Related Questions