如何将 Eithers 列表更改为左右两个值列表。当我使用partition
它时,它会返回两个非值的列表。最简单的方法是什么?
问问题
193 次
4 回答
6
foldLeft
允许您轻松编写自己的方法:
def separateEithers[T, U](list: List[Either[T, U]]) = {
val (ls, rs) = list.foldLeft(List[T](), List[U]()) {
case ((ls, rs), Left(x)) => (x :: ls, rs)
case ((ls, rs), Right(x)) => (ls, x :: rs)
}
(ls.reverse, rs.reverse)
}
于 2014-07-03T14:35:07.113 回答
2
map
分区后,您必须得到两个结果列表。
val origin: List[Either[A, B]] = ???
val (lefts, rights) = origin.partition(_.isInstanceOf[Left[_]])
val leftValues = lefts.map(_.asInstanceOf[Left[A]].a)
val rightValues = rights.map(_.asInstanceOf[Right[B]].b)
如果您对演员表和 isInstanceOf 不满意,您也可以分两遍进行:
val leftValues = origin collect {
case Left(a) => a
}
val rightValues = origin collect {
case Right(b) => b
}
如果您对这两次通行证不满意,则必须“手动”完成:
def myPartition[A, B](origin: List[Either[A, B]]): (List[A], List[B]) = {
val leftBuilder = List.newBuilder[A]
val rightBuilder = List.newBuilder[B]
origin foreach {
case Left(a) => leftBuilder += a
case Right(b) => rightBuilder += b
}
(leftBuilder.result(), rightBuilder.result())
}
最后,如果你不喜欢可变状态,你可以这样做:
def myPartition[A, B](origin: List[Either[A, B]]): (List[A], List[B]) = {
@tailrec
def loop(xs: List[Either[A, B]], accLeft: List[A],
accRight: List[B]): (List[A], List[B]) = {
xs match {
case Nil => (accLeft.reverse, accRight.reverse)
case Left(a) :: xr => loop(xr, a :: accLeft, accRight)
case Right(b) :: xr => loop(xr, accLeft, b :: accRight)
}
}
loop(origin, Nil, Nil)
}
于 2014-07-03T14:24:29.150 回答
2
如果您可以通过列表进行两次遍历,则可以使用 collect:
type E = Either[String, Int]
val xs: List[E] = List(Left("foo"), Right(1), Left("bar"), Right(2))
val rights = xs.collect { case Right(x) => x}
// rights: List[Int] = List(1, 2)
val lefts = xs.collect { case Left(x) => x}
// lefts: List[String] = List(foo, bar)
于 2014-07-03T14:30:43.660 回答
1
像这样使用 for 理解,
for ( Left(v) <- xs ) yield v
和
for ( Right(v) <- xs ) yield v
于 2014-07-03T14:38:02.213 回答