【问题标题】:FlatMap or For-comprehension on a Nested Options Monad嵌套选项单子上的 FlatMap 或 For-comprehension
【发布时间】:2015-11-07 07:35:02
【问题描述】:

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

    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
      }
    }

【问题讨论】:

    标签: scala monads flatmap


    【解决方案1】:

    一个相对易读的直接转换是:

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

    这里要注意的是,我们将nightClubPeoples 转换为前面的列表,允许我们一直使用 for 理解。

    但是,当signficantOtherNone 时,我怀疑您是否真的希望在您的列表中显示“没有重要的其他人”。相反,它应该被忽略,这样会更简单:

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

    【讨论】:

      【解决方案2】:

      给你:

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

      【讨论】:

        【解决方案3】:

        我认为,Sascha Kolberg 的答案是一个更好的解决方案(只需省略 signficantOther 为空时的情况,即“No Signficant Other”不会出现在结果列表中),但是自从 您要求“将其转换为 flatMap 或用于理解”,因此代码如下。

        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))
        

        【讨论】:

          【解决方案4】:

          我想我会使用折叠:

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

          【讨论】:

            猜你喜欢
            • 2014-07-04
            • 1970-01-01
            • 2019-02-18
            • 2013-12-25
            • 2018-04-26
            • 2016-11-10
            • 2016-12-25
            • 2020-08-22
            • 1970-01-01
            相关资源
            最近更新 更多