如何拆分列表[[A,B]]

Yan*_*san 19 scala either

我想拆分List[Either[A, B]]两个列表.

有没有更好的办法 ?

def lefts[A, B](eithers : List[Either[A, B]]) : List[A] = eithers.collect { case Left(l) => l}
def rights[A, B](eithers : List[Either[A, B]]) : List[B] = eithers.collect { case Right(r) => r}
Run Code Online (Sandbox Code Playgroud)

Mar*_*rth 23

不确定这是否真的更整洁,但是:

scala> def splitEitherList[A,B](el: List[Either[A,B]]) = {
         val (lefts, rights) = el.partition(_.isLeft)
         (lefts.map(_.left.get), rights.map(_.right.get))
       }
splitEitherList: [A, B](el: List[Either[A,B]])(List[A], List[B])

scala> val el : List[Either[Int, String]] = List(Left(1), Right("Success"), Left(42))
el: List[Either[Int,String]] = List(Left(1), Right(Success), Left(42))

scala> val (leftValues, rightValues) = splitEitherList(el)
leftValues: List[Int] = List(1, 42)
rightValues: List[String] = List("Success")
Run Code Online (Sandbox Code Playgroud)

  • 编辑:(lefts.map(_.left.get),rights.map(_.right.get))变为(lefts.flatMap(_.left.toOption),rights.flatMap(_.right.toOption)) (3认同)

Fil*_*ale 15

如果scalaz是您的依赖项之一,我会简单地使用separate:

import scalaz.std.list._
import scalaz.std.either._
import scalaz.syntax.monadPlus._

val el : List[Either[Int, String]] = List(Left(1), Right("Success"), Left(42))

scala> val (lefts, rights) = el.separate
lefts: List[Int] = List(1, 42)
rights: List[String] = List(Success)
Run Code Online (Sandbox Code Playgroud)

  • 注意为所有必需的进口提供更完整的答案?而具体的scalaz版本? (3认同)
  • 如果你使用`cats`,你也可以"分开"!http://typelevel.org/cats/api/cats/syntax/SeparateOps.html#separate(implicitF:cats.MonadCombine[F],implicitG:cats.Bifoldable[G]):(F[A],F[B ]) (3认同)

Xav*_*hot 12

首先Scala 2.13,现在为大多数集合提供了一种partitionMap方法,该方法根据返回Right或的函数对元素进行分区Left

在我们的例子中,我们甚至不需要像我们已经拥有s和s 那样将输入转换为RightLeft定义分区的函数。因此简单使用:RightLeftidentity

val (lefts, rights) = List(Right(2), Left("a"), Left("b")).partitionMap(identity)
// lefts: List[String] = List(a, b)
// rights: List[Int] = List(2)
Run Code Online (Sandbox Code Playgroud)


rot*_*erl 9

你可以这样做:

val (lefts, rights) = eithers.foldRight((List[Int](), List[String]()))((e, p) => e.fold(l => (l :: p._1, p._2), r => (p._1, r :: p._2)))
Run Code Online (Sandbox Code Playgroud)


Vas*_*kov 8

紧凑但不是CPU效率的解决方案:

val lefts = list.flatMap(_.left.toOption)
val rights = list.flatMap(_.right.toOption)
Run Code Online (Sandbox Code Playgroud)