简体   繁体   中英

Flatten List[Either[A, B]] to List[B] like List[Option[B]] to List[B]

Does Cats provide flattening akin to

implicit class FlattenListOfEither[L, R](l: List[Either[L, R]]) {
  def flattenM: List[R] = l collect { case Right(v) => v }
}

such that

val l1: List[Either[String, Int]] = List(Right(1), Right(2), Left("error"), Right(4))
l1.flattenM

outputs

List(1, 2, 4)

similar to how vanilla Scala flattens list of options

val l2: List[Option[Int]] = List(Some(1), Some(2), None, Some(4))
l2.flatten

which outputs

List(1, 2, 4)

separate gives the following syntax

import cats.implicits._
val (_, rights) = l1.separate
rights

which outputs

List(1, 2, 4)

however does there exist out-of-the-box flatten -like extension method which returns just the rights instead of the tuple?

I think the easiest is to use mapFilter provided by the FunctorFilter typeclass. It looks like this:

def mapFilter[A, B](fa: F[A])(f: (A) ⇒ Option[B]): F[B]

Where F[A] could be List[A] , or Vector[A] or any other type that allows filtering.

If we apply this function to your list, we just need to turn the Either[A, B] s into Option[B] s. This is as easy as calling toOption . With that the full solution looks like this:

import cats.implicits._

val l1: List[Either[String, Int]] = List(Right(1), Right(2), Left("error"), Right(4))

l1.mapFilter(_.toOption)
// List(1, 2, 4)

I just wanted to remark that

listOfEithers.flatMap(_.toOption)

with plain vanilla Scala-collection methods seems to do what you want:

val x = List(Right(1), Right(2), Left("error"), Right(4))
x.flatMap(_.toOption) // res0: List[Int] = List(1, 2, 4)

What about partitionMap in Scala 2.13 ? (note sure what you mean by shorter ):

   val l1: List[Either[String, Int]] = List(Right(1), Right(2), Left("error"), Right(4))
    val (_, rights) = l1.partitionMap(identity)
    println(rights)
 // Displays
 // List(1, 2, 4)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM