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)
}
我对这个简单的 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)
}