Skip to content

Instantly share code, notes, and snippets.

@lloydmeta
Last active August 29, 2015 14:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lloydmeta/4d4024e3ab7d283ec9a4 to your computer and use it in GitHub Desktop.
Save lloydmeta/4d4024e3ab7d283ec9a4 to your computer and use it in GitHub Desktop.
Lazy generic dropMax in Scala so you can work with infinitely (why? dunno) long traversables. Should be fairy efficient wrt traversal complexity, stack and heap used.
import scala.collection.generic.CanBuildFrom
import scala.language.higherKinds
/**
* Returns the input collection without the biggest element.
*/
def dropMax[A, T[A] <: Traversable[A]](coll: T[A])(implicit ord: Ordering[A], cbf: CanBuildFrom[_, A, T[A]]): T[A] = {
def streamWithoutMax(currentMax: A, listTail: Traversable[A]): Stream[A] = {
if (listTail.isEmpty) {
Stream.Empty
} else {
val listHead = listTail.head
val (nextItem, nextMax) = (ord.min(currentMax, listHead), ord.max(currentMax, listHead))
nextItem #:: streamWithoutMax(nextMax, listTail.tail)
}
}
if (coll.isEmpty) {
coll
} else {
val lazyDropped: Iterator[A] = streamWithoutMax(coll.head, coll.tail).toIterator
val builder = cbf()
builder ++= lazyDropped
builder.result
}
}
// ---- Example usage
/*
scala> dropMax(Seq(1,2,34,5,3,2))
res9: Seq[Int] = Vector(1, 2, 5, 3, 2)
scala> dropMax(List(1,2,34,5,3,2))
res10: List[Int] = List(1, 2, 5, 3, 2)
scala> dropMax(Set(1,2,34,5,3,2))
res11: scala.collection.immutable.Set[Int] = Set(1, 2, 5, 3)
scala> val maxLessStream = dropMax(Stream(14,1435,416,146,4163,143))
maxLessStream: scala.collection.immutable.Stream[Int] = Stream(14, ?)
scala> maxLessStream.foreach(println(_))
14
416
146
1435
143
scala> import scala.util.Random
import scala.util.Random
scala> val infStream = Stream.iterate(1)(_ => Random.nextInt())
infStream: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> val maxLessInfStream = dropMax(infStream)
maxLessInfStream: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> maxLessInfStream.take(10).foreach(println(_))
1
1401725142
-774843147
1762614257
-471406408
968838195
-319423164
1170162441
903940679
-1743341984
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment