从 Option[String] 中提取值的 Scala 方法是什么?

时间:2021-04-08 14:29:10

标签: scala

我正在尝试从 Option[String] 中提取辅助和事件类型,提取这些值的最佳 Scala 方法是什么,如果没有,则输出为 null。

val payload = Some({"event":"testApi",
    "data":[{"aid":"test","pr":"{\"id\":\"813da0e5-d9aa-4275-b9d4-5e84362b73bb\",\"event_type\":\"promo app loaded\",\"label\":\"beach apartheid\",\"total\":1,\"timestamp\":1617891494152}}]",
    "tv":"js-2.17.3"
    })

如果我有这个如何提取其他然后如果其他。

2 个答案:

答案 0 :(得分:3)

这取决于您之后要对这个有效载荷做什么。 Option 是一个 monad,所有的标准操作,如 .mapflatMap.foreach.filter.collect 等。适用于它。我真的建议您阅读 scala monads 以更好地掌握它。

简而言之,你应该构造你的代码,这样你就永远不需要执行 option.get 来访问实际值,几乎永远不要执行 option.isEmpty(或 option.nonEmpty,并且很少,如果永远做.getOrElse(例如val unwrappedJson = payload.getOrElse('{}'))。

在大多数情况下,我也会避免模式匹配,尽管在另一个答案中提到的那本书暗示了什么。它可能是“最常见的”,但在大多数情况下不是“最好的”(不过,这开始进入“个人品味”领域,模式匹配在技术上没有任何问题,只是它不是“一元的” “并因此有些难以阅读和视觉分析)。

一些你可以做的事情的例子:

    def parsePayload(maybePayload: Option[String]): Option[Payload] = 
       maybePayload.map(json.readValue[Payload])
   
    ...
    
    def getLabels(maybePayload: Option[String]): Seq[String] = maybePayload
        .map(json.readValue[Payload])
        .toSeq
        .flatMap(_.data)
        .map(_.pr.label)


    ...

    def uniqueIds(maybePayload: Option[String]): Seq[String] = maybePayload
       .map(json.readValue[Payload])
       .toSeq
       .flatMap(_.data)
       .map(_.pr.id)
       .distinct

    ...


    def maybeData(maybePayload: Option[String]): Seq[Data] = 
       parsePayload(maybePayload)
         .fold(Seq.empty[Data])(_.data)

    ...


    def byId(maybePayload: Option[String]): Map[String, Seq[Data]] = maybePayload
       .map(json.readValue[Payload])
       .toSeq
       .flatMap(_.data)
       .groupBy(_.pr.id)
       .map { case(id, datas) => datas }
       
    def forId(maybePayload: Option[String], id: String): Seq[Data] = maybePayload
       .map(json.readValue[Payload])
       .toSeq
       .flatMap(_.data.filter(_.pr.id == id))
     ...

    def forId2(maybePayload: Option[String], id: String): Seq[Data] = 
       byId(maybePayload).getOrElse(id)

    ...

    def maxTotal(maybePayload: Option[String]): Option((String, Int)) = 
      parsePayload(maybePayload)
      .collect { case Payload(_, data, _) if data.nonEmpty => data.maxBy(_.pr.total) }
      .map { case data => data.pr.id -> data.pr.total }
         
    ...  

 
    def printPayload(maybePayload: Option[String]): Unit = 
       maybePayload.foreach(println)

答案 1 :(得分:0)

根据由 artima 出版的“Scala 编程,第 3 版”一书,它说:

<块引用>

“分离可选值的最常见方法是通过模式匹配。”

示例:

def show(x: Option[String]): String = x match {
  case Some(s) => s
  case None => "?"
}
相关问题