【问题标题】:Take the element in a list that satisfy a condition获取列表中满足条件的元素
【发布时间】:2017-06-16 06:11:03
【问题描述】:

我有一个List[Either[Error, Satisfaction]],我需要获取该列表中isRight 的第一个元素。如果没有满足isRight的元素,那么我应该返回最后一个Error

现在我想到了takeWhile(_.isLeft),找到最后一个列表的大小,然后在原始列表中获取nth 元素,n 是第一个左列表的大小,但我认为对此有更好的解决方案。

我们将不胜感激。

【问题讨论】:

    标签: scala scala-collections


    【解决方案1】:

    您可以像这样reduce 列表:

    lst.reduceLeft((a,b) => if (a.isRight) a else b)
    

    结果将是第一个 Right 元素,如果没有,则为最后一个 Left 元素。

    【讨论】:

    • 这很聪明。我能看到的唯一缺点是,如果早期发现 Right 元素,它不会“短路”。但我能想到的唯一方法就是编写更多代码。
    • @JoeK,我同意。提前终止会很好。它可以通过递归来完成,但正如你所说,更多的代码。事实上,我在想 this 太冗长了。由于Either[] 现在偏右,我们应该能够做类似a orElse b 的事情。也许在 Scala 2.13 中。
    【解决方案2】:

    您可以这样做,这与@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)
    • 连续第二次给出一个可以简化很多的答案。是时候睡觉了:)
    猜你喜欢
    • 1970-01-01
    • 2020-01-22
    • 2021-02-15
    • 2011-04-16
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多