Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Seeking a scala-esque approach to iterate through a list with access to the "next" element

I am working on a Polygon class which holds an array of vertices in an Array[Vec2] (with Vec2 being a simple case class defining x and y).

Now, I would like to implement a function to return the edges of the polygon in an Array[LineSegment] (where LineSegment is again a simple case class which defines start and end).

The solution is to create line segments connecting each vertex to the next in the array, and finally connecting the last vertex to the first.

I'm only used to imperative programming, so this is my imperative approach:

def edges: Array[LineSegment] = {
  val result = new Array[LineSegment](vertices.length)

  for (i <- 0 to vertices.length - 2) {
    result.update(i, LineSegment(vertices.apply(i), vertices.apply(i + 1)))
  }
  result.update(edges.length - 1, LineSegment(vertices.head, vertices.last))

  result
}

This works fine, but it's plain ugly. I want to use the advantages of functional programming here, but I'm kinda stuck with that.

My idea was to put it like something similar to this:

def edges: Array[LineSegment] = {
    for (v <- vertices) yield 
      LineSegment(v, if (v == vertices.last) vertices.head else /* next? */)
}

The problem is that there's no way to access the next item in the array given the current item v.

I've read about the sliding method defined in IterableLike, however that seems to be non-rotating, ie it will not consider the first item to be subsequent to the last item and therefore not return it.

So what is a good "scala-esque" approach to this?

like image 229
pdinklag Avatar asked Dec 05 '22 23:12

pdinklag


1 Answers

Of course you can use sliding:

(vertices :+ vertices.head) sliding 2
like image 68
Debilski Avatar answered Jan 18 '23 22:01

Debilski