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

时间:2015-01-13 11:39:01

标签: scala

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

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

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

即使确定 nextUrl 中有值,所有Tuple都是空的。

完整的方法

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

  }

感谢,

三木

2 个答案:

答案 0 :(得分:1)

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

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

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

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

答案 1 :(得分:0)

可能你需要这样的东西:

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