过滤一组Either[x, y],记录

The*_*ude 4 functional-programming scala either

给定 a Set[Either[BadObject, GoodObject]],我想将其转换为 a Set[GoodObject],同时记录所有BadObjects.

我遇到的问题是,当我尝试在collect呼叫中添加日志记录时,例如:

someMethodThatReurnsTheSet.collect {
  case Right(value) => value
  case Left(res) => logger.warn(s"Bad object : $res")
}
Run Code Online (Sandbox Code Playgroud)

这改变了返回值,我得到了一个Set[None],这不是我想要的。

Mar*_*lic 6

尝试partition结合链接

import util.chaining._

someMethodThatReurnsTheSet
  .partition(_.isRight)
  .tap { case (_, lefts) => logger.warn(s"Bad objects $lefts") }
  .pipe { case (rights, _) => rights }
Run Code Online (Sandbox Code Playgroud)

  • 应该提到这仅适用于 Scala 2.13。* (4认同)

bot*_*aio 5

简单的方法:

someMethodThatReurnsTheSet().collect {
  case Right(value) => Some(value)
  case Left(res) => 
    logger.warn(s"Bad object : $res")
    None
}.flatten
Run Code Online (Sandbox Code Playgroud)

许多替代方案都是可能的,例如或查看其他答案:)

val (lefts, rights) = someMethodThatReurnsTheSet().partition(_.isLeft)
lefts.foreach(err => logger.warn(s"Bad object : ${err.left.get}"))
val set = rights.map(_.right.get)
Run Code Online (Sandbox Code Playgroud)


Yuv*_*kov 5

另一种使用方式foldLeft

someMethodThatReturnsTheSet.foldLeft(Set.empty[GoodObject]) {
   case (acc, goodOrBad) => goodOrBad match {
     case Right(good) => acc + good
     case Left(bad) => 
       logger.warn("Bad object: $bad")
       acc
   }
}
Run Code Online (Sandbox Code Playgroud)

如果您不介意分配:

someMethodThatReturnsTheSet.flatMap {
  case Right(good) => Set(good)
  case Left(bad) => 
    logger.warn("Bad object: $bad")
    Set.empty
}
Run Code Online (Sandbox Code Playgroud)