嵌套选项Monad上的FlatMap或For-comprehension

时间:2015-08-14 06:12:28

标签: scala monads flatmap

有人可以帮助我将其转换为flatMap或for -reherehension吗?我知道如何处理嵌套选项的更多琐碎场景。

    case class Person(name: String, signficantOther: Option[String])
    val nightclubPeoples : Option[Seq[Person]] = ???

    def significantOthers(nightClubPeoples : Option[Seq[Person]]) : List[String] = {
      nightclubPeoples match {
        case Some(x) => x map { y : Person => 
          y.significantOther match {
            case Some(z) => z
            case None => "No Signficant Other"
          }
        }.toList
        case None => Nil
      }
    }

4 个答案:

答案 0 :(得分:0)

我想我会使用折叠:

nightclubPeoples.fold[List[String]](Nil)(_.flatMap(_.signficantOther)(collection.breakOut))

答案 1 :(得分:0)

正如我认为的那样,Sascha Kolberg的回答是更好的解决方案(只是在signficantOther为空时省略,即&#34; No Signficant Other&#34;不会在结果列表中< / strong>)因为你的问题 你要求&#34;将其转换为flatMap或for-comprehension&#34;,所以代码如下。

case class Person(name: String, signficantOther: Option[String])
val nightClubPeopleOpt : Option[Seq[Person]] = Some(Person("name", Some("1")) :: Person("name1", None) :: Nil)

def significantOthers(nightClubPeopleOpt : Option[Seq[Person]]) = {
    for {
        nightClubPeople <- nightClubPeopleOpt
    } yield {
        // scenario 1
        // if signficantOther is empty, then it should be ignored
        // Answer -> List(1)
        nightClubPeople.flatMap(_.signficantOther).toList

        // scenario 2
        // if signficantOther is empty, then we use the default "No Signficant Other"
        // Answer -> List(1, No Signficant Other)
        nightClubPeople.map { nightClubPerson =>
            nightClubPerson.signficantOther.getOrElse("No Signficant Other")
        }.toList
    }
}.getOrElse(Nil)


println(significantOthers(nightClubPeopleOpt))

答案 2 :(得分:0)

你走了:

nightclubPeoples.toSeq.flatMap(_.map(_.signficantOther.getOrElse("No Signficant Other")))

答案 3 :(得分:0)

相对可读的直接转换是:

def significantOthers(nightClubPeoples : Option[Seq[Person]]): List[String] = {
  for {
    nightClubPeoples <- nightClubPeoples.toList
    person <- nightClubPeoples
  } yield person.significantOther.getOrElse("No Significant Other")
}

这里要注意的是我们将nightClubPeoples转换为预先列表,允许我们一直使用for for comprehension。

但是,当signficantOtherNone时,我怀疑您确实希望列表中显示“无显着其他”。相反,它应该被忽略,这将使更简单:

def significantOthers(nightClubPeoples : Option[Seq[Person]]): List[String] = {
  for {
    nightClubPeoples <- nightClubPeoples.toList
    person <- nightClubPeoples
    significantOther <- person.significantOther
  } yield significantOther
}