【问题标题】:Scala: Conditionally add element in a Map definition based on pattern matchScala:根据模式匹配有条件地在地图定义中添加元素
【发布时间】:2017-09-09 15:56:14
【问题描述】:

我正在尝试在当前项目中尽可能多地使用 Scala 功能,但我很难在 Map 定义中使用模式匹配。

为了说明这一点,请考虑以下代码 sn-p:

class Foo(val element: Option[Any], val element2: Any, ...)
val bar = new Foo(...)
val map = Map(bar.element match {
                      case None => ??? // Do not add an item here
                      case Some(el) => "element" -> el
                  }, "element2" -> element2, ...
              )

我在这段代码 sn-p 中遇到的问题是 None 的情况。如何指定此处不应添加任何元素?

我已经尝试了几件事:

  • 我不能在这里引入{},因为它会被解释为Unit
  • case None => 后面留一个空格会导致类型不匹配;因为它也被视为Unit,而我们需要Tuple2
  • 我可以在Map 定义之后执行模式匹配,只在Some(el) 的情况下添加一个元素。但是,这并不是一种非常优雅的方式。
  • 我可以完全省略 case None =>,但这会产生警告,因为匹配并不详尽,如果元素确实是 None,则会失败。

如果我想涵盖 Map 定义中的所有情况,我该如何指出在None 的情况下,不应添加任何元素?

一些上下文:我将它用作(akka)喷雾 json 协议定义的一部分,用于某种类型,并且想知道是否有一种速记方法可以做到这一点,而不需要有条件地向地图添加元素。

提前致谢!

编辑:建议的解决方案

根据mavarazy 的回答,我通过如下代码解决了这个问题:

class Foo(val element: Option[Any], val element2: Any, ...)
val bar = new Foo(...)
val map = Map(bar.element match {
                      case None => "" -> null // Do not add an item here
                      case Some(el) => "element" -> el
                  }, "element2" -> element2, ...
              ).filter(_._2 != null)

从未想过这样做,但我认为它仍然有些优雅。谢谢!

【问题讨论】:

    标签: scala dictionary pattern-matching


    【解决方案1】:

    在选项 3 上,您可以通过将 .map 替换为接收部分函数的 .collect 来删除 None 情况

    【讨论】:

      【解决方案2】:

      从我的角度来看,选项3没有错,但如果你不喜欢它,你也可以这样做:

      val map = Map(
        "element" -> element,
        "element2" -> Option(element2)
      ).
        filter(_._2.isDefined).
        mapValues(_.get)
      

      如果这是您的顾虑之一,它还会阻止您在 element2 中使用 null 值的 Map

      【讨论】:

      • 这对我有用。我可以将它作为第四个选项的一部分。但是,我使用了一个稍微不同的方案——在None 的情况下,我添加"" -> null 并将其过滤掉。从来没有想过这样做。谢谢!如果我的声誉允许,我会投票。
      • 这很好,但在 Scala 中你应该避免使用 null,而更喜欢 Option。对于 Java8 也是如此,其中有一个单独的 Option 类,您应该在 return 语句中使用它,以防可空值
      【解决方案3】:

      使用“收集”是我的偏好,因为它需要一个部分函数,​​即只收集那些与部分函数中指定的模式匹配的值 -

      val map: Map[String, Option[String]] = Map(
        "element" -> Some("element"),
        "element2" -> Some("element2"),
        "element3" -> None
      )
      map collect { case (s, Some(e)) => (s, e) }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-24
        • 1970-01-01
        • 2021-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-09
        • 2012-11-07
        相关资源
        最近更新 更多