【问题标题】:How do you convert option to None?你如何将选项转换为无?
【发布时间】:2015-12-01 10:00:26
【问题描述】:

考虑example

object Main extends App {
  case class ref(val target: Object)
  val map: Map[Int, ref] = Map(1 -> ref(null), 2 -> ref("2")) 
                                            //> map  : Map[Int,o.ref] = Map(1 -> ref(null), 2 -> ref(2))

  def request(id: Int, default: Object) = {
    println(map.get(id) map (_.target) match {
      case Some(result) => result
      case None => default
    })
  }                                         //> request: (id: Int, default: Object)Unit
  request(0, "fixed 0")                     //> fixed 0
  request(1, "fixed 1")                     //> null
  request(2, "fixed 2")                     //> 2
}

如您所见,option1 的结果为 null。我希望这样的目标能够处理同样的数据库中没有匹配项。如何将Some(null) 转换为None

【问题讨论】:

  • 通常我会查看“目标”值的来源,并将它们包装在Option 中,尽可能接近该点。然后,'null' 值将已经是 None,而非空值将是 Some(target)。例如,在此调用.map(ref) 以获取None/Some(ref),在其上调用.foreach 以将条目放入地图中(因此只有当它不是None 时才会进入)等等。
  • 目标来自弱引用。我不想花费大量内存将所有内容存储在 Option 包装器中。然而,动态转换它的想法是有道理的。

标签: scala monads optional


【解决方案1】:

你可以使用filter:

map (_.target) filter (_ != null)

【讨论】:

    【解决方案2】:

    一般来说,如果您想将可能是null 的值转换为Option,只需像这样构建它:

    Option(ref)
    

    在您的情况下,由于您希望内部字段成为Option,您可以只使用flatMap

    map.get(id).flatMap(ref => Option(ref.target))
    

    我会重写你的 request 方法:

    def request(id: Int, default: Object) =
      println(map.get(id).flatMap(ref => Option(ref.target)).getOrElse(default))
    

    Option 的 apply 方法完全符合您的要求,如果您将 null 传递给它,它将返回一个 None,这就是 flatMap 位的工作原理。

    【讨论】:

    • 映射所有地图值似乎有点过头了。 map.get(id).filter(_.target != null).getOrElse(default)is just fine.
    • @ValentinTihomirov 我更新了我的答案以适应您的建议。您编写的确切表达式将返回ref,而不是目标,您需要在getOrElse 部分之前map
    • mapValues 实际上并没有映射,而是创建了一个可以按需应用映射函数的视图。 scala-lang.org/api/2.11.7/…
    • 是的,你没事。我选择了 Lee 的答案,因为它解决了真正的问题,即如何以最简洁的形式转换 Some(null) => None。但你的说法是恰当的。
    【解决方案3】:

    最新,我最好的匹配是使用 flatMap

    map (_.target) flatMap { case null => None ; case a => Some(a) } 
    

    【讨论】:

    • 这相当于:map(_.target).flatMap(item=>Option(item))
    【解决方案4】:

    调用map.get(1) 将返回Some(ref(null))。执行Some(ref(null)) map (_.target) 会导致Some(null)。这就是你得到空值的原因。你可以这样做:

    def request(id: Int, default: Object) = {
        println(map.get(id).flatMap(r => Option(r.target)).getOrElse(default))
    }
    

    现在request(1, "fixed 1") 将打印fixed 1

    此外,您的最终match 表达式可以缩短为getOrElse(default)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      • 1970-01-01
      • 2010-09-21
      • 1970-01-01
      相关资源
      最近更新 更多