【发布时间】:2017-06-16 06:11:03
【问题描述】:
我有一个List[Either[Error, Satisfaction]],我需要获取该列表中isRight 的第一个元素。如果没有满足isRight的元素,那么我应该返回最后一个Error。
现在我想到了takeWhile(_.isLeft),找到最后一个列表的大小,然后在原始列表中获取nth 元素,n 是第一个左列表的大小,但我认为对此有更好的解决方案。
我们将不胜感激。
【问题讨论】:
我有一个List[Either[Error, Satisfaction]],我需要获取该列表中isRight 的第一个元素。如果没有满足isRight的元素,那么我应该返回最后一个Error。
现在我想到了takeWhile(_.isLeft),找到最后一个列表的大小,然后在原始列表中获取nth 元素,n 是第一个左列表的大小,但我认为对此有更好的解决方案。
我们将不胜感激。
【问题讨论】:
您可以像这样reduce 列表:
lst.reduceLeft((a,b) => if (a.isRight) a else b)
结果将是第一个 Right 元素,如果没有,则为最后一个 Left 元素。
【讨论】:
Right 元素,它不会“短路”。但我能想到的唯一方法就是编写更多代码。
Either[] 现在偏右,我们应该能够做类似a orElse b 的事情。也许在 Scala 2.13 中。
您可以这样做,这与@jwvh 的回答存在双重问题:如果rest 为空,则必须再次遍历列表。
val (lefts, rest) = list.span(_.isLeft)
rest.headOption.getOrElse(lefts.last)
// or orElse(lefts.lastOption) if list can be empty
并且没有任何完整性问题的递归解决方案(假设非空列表):
def foo(list: List[Either[Error, Satisfaction]]) = list match {
case x :: tail => if (x.isRight || tail.isEmpty) x else foo(tail)
}
不是那更多的代码。
【讨论】:
lst.find(_.isRight).getOrElse(lst.last)