Skip to content

Instantly share code, notes, and snippets.

@hanbzu
Created October 31, 2013 07:40
Show Gist options
  • Select an option

  • Save hanbzu/7245661 to your computer and use it in GitHub Desktop.

Select an option

Save hanbzu/7245661 to your computer and use it in GitHub Desktop.
Scala: filtering operation. Didactic
// Filtering elements in a list (here they're kept if positive)
def posElems(xs: List[Int]): List[Int] = xs match {
case Nil => xs
case y :: ys => if (y > 0) y :: posElems(ys) else posElems(ys)
}
// A simple way to define filter
// In reality it's more complicated because:
// * It works for arbitrary collections, not only lists
// * Its tail recursive
abstract class List[T] {
...
def filter(p: T => Boolean): List[T] = this match {
case Nil =>
case x :: xs => if (p(x)) xx :: xs.filter(p) else xs.filter(p)
}
}
// Back to posElems
def posElems(xs: List[Int]): List[Int] = xs filter (x => x > 0)
// Now real world examples of filtering
xs filter p
xs filterNot p // Elements that do not satisfy predicate p
xs partition p // A par containing those who satisfy p and those who dont
xs takeWhile p // Longest prefix of xs that satisfy p
xs dropWhile p // Remainder of xs after leading elements that satisfy p removed
xs span p // (xs takeWhile p, xs dropWhile p) but faster
val nums = List(2, -4, 5, 7, 1)
nums filter (x => x > 0) // List(2, 5, 7, 1)
nums filterNot (x => x > 0) // List(-4)
nums partition (x => x > 0) // (List(2, 5, 7, 1), List(-4))
nums takeWhile (x => x > 0) // List(2)
nums dropWhile (x => x > 0) // List(-4, 5, 7, 1)
nums span (x => x > 0) // (List(2), List(-4, 5, 7, 1))
// EXAMPLE1: Pack consecutive duplicates into sublists
// pack(List("a", "a", "a", "b", "c", "c", "a")) should give
// List(List("a", "a", "a"), List("b"), List("c", "c"), List("a"))
def pack[T](xs: List[T]): List[List[T]] = xs match {
case Nil => Nil
case x :: xs1 =>
val (first, rest) = xs span (y => x == y)
first :: pack(rest)
}
// EXAMPLE2: Encode the run-length encoding of a list
// encode(List("a", "a", "a", "b", "c", "c", "a")) should give
// List(("a", 3), ("b", 1), ("c", 2), ("a", 1))
def encode[T](xs: List[T]): List[(T, Int)] = {
pack(xs) map (ys => (ys.head, ys.length)) // We use pack, and map!
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment