【问题标题】:Fetch elements from Option[Any] of List从 List 的 Option[Any] 中获取元素
【发布时间】:2019-05-22 21:20:33
【问题描述】:
scala> val a  = jsonMap.get("L2_ID")
a: Option[Any] = Some(List(24493, 22774, 23609, 20517, 22829, 23646, 22779, 23578, 22765, 23657))

我想获取列表的第一个元素,即 24493。所以,尝试以下代码:

scala> var b = a.map(_.toString)
b: Option[String] = Some(List(24493, 22774, 23609, 20517, 22829, 23646, 22779, 23578, 22765, 23657))

scala>

scala>  var c = b.map(_.split(",")).toList.flatten
c: List[String] = List(List(24493, " 22774", " 23609", " 20517", " 22829", " 23646", " 22779", " 23578", " 22765", " 23657)")

scala> c(0)
res34: String = List(24493

这没有按预期返回。请提出建议。

【问题讨论】:

  • Any 通常是有问题的症状

标签: scala list option


【解决方案1】:

我建议你使用模式匹配。 为了防御,我还添加了Try 以防止您的 json 不是数字列表的情况。 下面的代码返回一个Option[Int],你可以在上面调用.getOrElse(0)——或者其他一些默认值,如果你喜欢的话。

import scala.util.Try

val first = a match {
  case Some(h :: _) => Try(h.toString.toInt).toOption
  case _ => None
}

【讨论】:

  • @KamalKishore 如果这个答案解决了您的问题,那么请将问题标记为accepting this answer已解决。
【解决方案2】:

所以,你有一个 OptionList 在里面。然后scala> var b = a.map(_.toString)OptionList)的内容转换为String。那不是你想要的。 查看转换结果的类型,它们可以为您提供很好的提示。比如b: Option[String],告诉你列表丢了……

 a.map(_.map(_.toString))

另一方面,具有Option[List[String]] 类型:您已将列表中的每个元素都转换为字符串。

如果您只是在寻找第一个元素,则无需转换所有元素。这样的事情会做:

 a
  .flatMap(_.headOption) // Option[Int], containing first element or None if list was empty or id a was None
  .map(_.toString) // convert Int inside of Option (if any) to String
  .getOrElse("")   // get the contents of the Option, or empty string if it was None

【讨论】:

    【解决方案3】:

    如果您确定它是Some,并且列表不为空,那么您可以打开选项并使用.get 获取List[Int]。然后您可以使用.head 访问列表的第一个元素:

    val x: Option[List[Int]] = ???
    x.get.head
    

    如果您不在 REPL 中,并且不确定是 Some 还是 None,以及 List 是否有任何元素,请使用

    x.flatMap(_.headOption).getOrElse(yourDefaultValueEg0)
    

    在具有如此强大类型系统的语言中,当然不需要“字符串类型”编程,因此将所有内容转换为字符串并用逗号分隔是一种严重缺陷的方法。

    【讨论】:

    • 这不是一个好的答案,因为它鼓励了不安全的模式(.get.head 可以抛出空的 Option/Seq)。此外,它不起作用,因为您不能在 Any 上 .headOption
    • @PhilippM 哦...好吧,诚然,我错过了Option[Any] 部分。但是我不知道您在哪里发现了使用不安全模式的任何“鼓励”:我的回答的整个后半部分显示了如何正确使用flatMapgetOrElse。在交互式 REPL 会话期间没有必要写出 .flatMap...getOrElse,如果已经可以看到它是 Some(List(34567, ...))
    • a.get.head 只是导致错误的糟糕风格,正如我之前的评论所指出的那样。我不建议将此作为语言新手的解决方案。通过以这种方式开始您的答案,您确实鼓励 OP 使用此 API。您答案的后半部分也是损坏的代码。也许您可以通过修复示例并指出前半部分的缺陷来改进这一点
    • 它不会导致错误。在输入val a = Some(List(24493)) 时,它会导致24493,而不是其他任何东西。同样,Some(List(24493)).flatMap(_.headOption).getOrElse(42) 编译和运行都很好,在什么意义上它“坏”了?
    • 尝试 None.get 或 Nil.head。是的,如果 JSON 对象不符合预期的形状,这些都是错误。如果您将a 作为OP 定义的,那么您的代码将不起作用。请将其复制/粘贴到 REPL 中以找出原因,或者再次阅读我对您的答案的第一条评论(任何未定义 .headOption 的 dos)。这将是我对你的回答的最后评论,我不是来教你 Scala 的,对不起。
    猜你喜欢
    • 1970-01-01
    • 2019-11-22
    • 1970-01-01
    • 1970-01-01
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 2017-12-28
    • 2012-07-30
    相关资源
    最近更新 更多