扁平化列表[E [er [A,B]]到列表[B]像列表[Option [B]]到列表[B]

时间:2019-07-31 22:54:07

标签: scala flatten scala-cats either

猫能使人扁平化吗?

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

如此

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

输出

List(1, 2, 4)

类似于香草Scala扁平化选项列表

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

输出

List(1, 2, 4)

separate提供以下语法

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

输出

List(1, 2, 4)

但是,有没有现成的flatten类扩展方法,它仅返回权限而不是元组?

3 个答案:

答案 0 :(得分:6)

我认为最简单的方法是使用mapFilter类型类提供的FunctorFilter。 看起来像这样:

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

F[A]可以是List[A]Vector[A]或任何其他允许过滤的类型。

如果我们将此功能应用于您的列表,只需要将Either[A, B]转换为Option[B]。这就像调用toOption一样容易。 完整的解决方案如下所示:

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)

答案 1 :(得分:2)

我只是想说明一下

listOfEithers.flatMap(_.toOption)

使用普通香草Scala收集方法似乎可以满足您的要求:

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

答案 2 :(得分:1)

<p id="demo" contenteditable="true"></p> 中的partitionMap呢? (请注意,Scala 2.13是什么意思)

shorter