Skip to content

Instantly share code, notes, and snippets.

@chris-martin
Last active December 22, 2015 02:59
Show Gist options
  • Save chris-martin/6407168 to your computer and use it in GitHub Desktop.
Save chris-martin/6407168 to your computer and use it in GitHub Desktop.

Some Scala-related thoughts on this Python function:

def GetContourPoints(self, array):
    """Parses an array of xyz points and returns a array of point dictionaries."""
    return zip(*[iter(array)]*3)

The most straightforward approach would be to use Iterable.grouped:

(1 to 8).grouped(3).map(_.toList).flatMap({
  case a::b::c::Nil => Some((a,b,c))
  case _ => None
}).toList
// List((1,2,3), (4,5,6))

To avoid creating the intermediary collections and only involve tuples, we could try using Iterable.zip:

def groupBy3[A](it: Iterator[A]): Iterator[(A,A,A)] = 
  ((it zip it) zip it).map({ case ((a, b), c) => (a,b,c) })
groupBy3((1 to 6).iterator).toList
// List((1,2,3), (4,5,6))

But this fails:

groupBy3((1 to 8).iterator).toList
// java.util.NoSuchElementException: next on empty iterator
//   at scala.collection.Iterator$$anon$2.next(Iterator.scala)

The operation could be implemented more directly without abusing Iterable.zip:

def groupBy3[A](it: Iterable[A]): Iterator[(A, A, A)] = new Iterator[(A, A, A)] {
  var s = it.toStream
  def hasNext = s.take(3).size == 3
  def next = { val t = (s(0), s(1), s(2)); s = s drop 3; t }
}
groupBy3(1 to 8).toList
// List((1,2,3), (4,5,6))

Frustratingly, Tuple3Zipped.Ops.zipped (provided implicitly by Predef.tuple3ToZippedOps) seems to provide something close to useful here, but the context bound requires that the tuple's types be IterableLike, and Iterator does not qualify.

I think this all just reiterates that tuples are tough to use elegantly in static type systems without dependent types (hence Tuple1, Tuple2, Tuple3, Tuple4, Tuple5, …).

Of course, the benefit of tuples over a Scala collection is static typing, which exists nowhere in Python. So a more apt comparison would simply be

(1 to 8).grouped(3).filter(_.size == 3).toList
// List(Vector(1, 2, 3), Vector(4, 5, 6))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment