Фильтрация набора Either [x, y] с ведением журнала - PullRequest
3 голосов
/ 02 апреля 2020

с заданным Set[Either[BadObject,GoodObject]], идентификатором нравится преобразовывать его в Set[GoodObject], при этом регистрируя все BadObjects. Проблема, с которой я столкнулся, заключается в том, что когда я пытаюсь добавить запись в вызове сбора, например

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

, это меняет возвращаемое значение, и я получаю Set [None], что не то, что я хочу.

Ответы [ 4 ]

6 голосов
/ 02 апреля 2020

Попробуйте partition в сочетании с цепочкой

import util.chaining._

someMethodThatReurnsTheSet
  .partition(_.isRight)
  .tap { case (_, lefts) => logger.warn(s"Bad objects $lefts") }
  .pipe { case (rights, _) => rights }
5 голосов
/ 02 апреля 2020

Другой способ использования 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
   }
}

Если вы не возражаете выделить:

someMethodThatReturnsTheSet.flatMap {
  case Right(good) => Set(good)
  case Left(bad) => 
    logger.warn("Bad object: $bad")
    Set.empty
}
4 голосов
/ 02 апреля 2020

Простой способ:

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

возможно много вариантов, например, или посмотрите другие ответы:)

val (lefts, rights) = someMethodThatReurnsTheSet().partition(_.isLeft)
lefts.foreach(err => logger.warn(s"Bad object : ${err.left.get}"))
val set = rights.map(_.right.get)
2 голосов
/ 02 апреля 2020

Если вы хотите выполнить действие только в Left случае, вы можете использовать .left.foreach:

setOfEithers.flatMap { e =>
    e.left.foreach { bad => logger.warn(s"Bad object: $bad") }
    e.toOption
}
...