Scala for yield 重新运行所有元组的空列表

Scala for yield rerun empty List for all the Tuples

我对这个简单的 yield 操作有一些疑问。

 for {
        relatedPostMd <- postMd.get.filter(_.fromID == userID)
        nextUrl <- (ch \ "paging" \ "next").asOpt[String] // string
      } yield  (nextUrl, relatedPostMd)

如果过滤结果为none(过滤操作不匹配)。

然后所有元组都是空的,即使我确定 nextUrl 中有值。

完整方法

 def getPostMD(userID: String, url: String): Future[List[(String, PostMD)]] = {


    val chunk: Future[JsValue] = Methods.getJsonValue(url)

    chunk.map(ch => {
      val postMd: Option[List[PostMD]] = (ch \ "data").asOpt[List[PostMD]]

      for {
        relatedPostMd <- postMd.get.filter(_.fromID == userID)
        nextUrl <- (ch \ "paging" \ "next").asOpt[String]
      } yield  (nextUrl, relatedPostMd)
    })

  }

谢谢,

三木

可能您需要这样的东西:

val postMd: Option[List[Int]] = ???
val next: Option[String] = ???

val defaultPostMd = -1
val defaultNext = ""
val nextVals = next.toList

val res = postMd
  .getOrElse(Nil)
  .filter(_ % 2 == 1) // << your filter
  .zipAll(nextVals, defaultPostMd, nextVals.lift(0).getOrElse(defaultNext))

1)

val postMd: Option[List[Int]] = Some(List(1, 2, 3, 4, 5))
val next: Option[String] = Some("next")

List((1,next), (3,next), (5,next))

2)

val postMd: Option[List[Int]] = None
val next: Option[String] = Some("next")

List((-1,next))

3)

val postMd: Option[List[Int]] = Some(List(1, 2, 3, 4, 5))
val next: Option[String] = None

List((1,), (3,), (5,))

4)

val postMd: Option[List[Int]] = None
val next: Option[String] = None

List()

for 理解力是 flatMap 的糖分。所以,你的代码基本上等同于:

postMd.get.filter(_.fromID == userID).map { relatedPostMd => 
   x
}

显然,当由 filter 编辑的 return 列表为空时,.map 结果会生成一个空列表。如果你想对这种情况进行一些特殊处理,你首先需要决定当没有匹配项时你想要元组的第二个元素是什么(以及你想要 return 多少个元组)。然后你可以这样做:

postMd.get.filter(_.fromID == userID) match {
   case Nil => List(whateverYourSentinelValueIs)
   case x => x
}.map { relatedPostMd => 
    ((ch \ "paging" \ "next"), relatedPostMd)
}