Skip to content

Instantly share code, notes, and snippets.

@dwijnand
Created January 16, 2013 11:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dwijnand/4546669 to your computer and use it in GitHub Desktop.
Save dwijnand/4546669 to your computer and use it in GitHub Desktop.
import collection.generic.CanBuildFrom
import collection.SeqView
class EitherSplit {
// Viktor Klang (@viktorklang), returns weird type
def split1(data: List[Either[String, Int]]): Either[SeqView[String, Seq[_]], SeqView[Int, Seq[_]]] =
data.partition(_.isLeft) match {
case (Nil, ints) => Right(for (Right(i) <- ints.view) yield i)
case (strings, _) => Left(for (Left(s) <- strings.view) yield s)
}
// Mine, fix return type
def split1fix(data: List[Either[String, Int]]): Either[List[String], List[Int]] = {
val either = data.partition(_.isLeft) match {
case (Nil, ints) => Right(for (Right(i) <- ints.view) yield i)
case (strings, _) => Left(for (Left(s) <- strings.view) yield s)
}
either match {
case Left(strings) => Left(strings.force.toList)
case Right(ints) => Right(ints.force.toList)
}
}
// Mine, fix return type
def split1fix2(data: List[Either[String, Int]]): Either[List[String], List[Int]] = {
val either = data.view.partition(_.isLeft) match {
case (Nil, ints) => Right(for (Right(i) <- ints) yield i)
case (strings, _) => Left(for (Left(s) <- strings) yield s)
}
either match {
case Left(view) => Left(view.force.toList)
case Right(view) => Right(view.force.toList)
}
}
// Chris Marshall (@oxbow_lakes)
def split2[X, CC[X] <: Traversable[X], A, B](l: CC[Either[A, B]])(implicit bfa: CanBuildFrom[Nothing, A, CC[A]],
bfb: CanBuildFrom[Nothing, B, CC[B]]): (CC[A], CC[B]) = {
def as = {
val bf = bfa()
bf ++= (l collect {case Left(x) => x})
bf.result()
}
def bs = {
val bf = bfb()
bf ++= (l collect {case Right(x) => x})
bf.result()
}
(as, bs)
}
// Mine
def split3(eithers: List[Either[String, Int]]): (List[Left[String, Int]], List[Right[String, Int]]) = {
val empty: (List[Left[String, Int]], List[Right[String, Int]]) = (Nil, Nil)
eithers.foldLeft(empty) {
case ((ls, rs), l@Left(_)) => (l :: ls, rs)
case ((ls, rs), r@Right(_)) => (ls, r :: rs)
}
}
// Mine, more generic
def split4[CC[X] <: Traversable[X], A, B](xs: CC[Either[A, B]])(implicit bfa: CanBuildFrom[Nothing, A, CC[A]],
bfb: CanBuildFrom[Nothing, B, CC[B]]): (CC[A], CC[B]) =
xs.foldLeft((bfa(), bfb())) {
case ((as, bs), l@Left(a)) => (as += a, bs)
case ((as, bs), r@Right(b)) => (as, bs += b)
} match {
case (as, bs) => (as.result(), bs.result())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment