如何判断 Map 是不是有默认值?
Posted
技术标签:
【中文标题】如何判断 Map 是不是有默认值?【英文标题】:How to tell if a Map has a default value?如何判断 Map 是否有默认值? 【发布时间】:2014-09-02 08:18:03 【问题描述】:有没有办法检查Map
是否有定义的默认值?我想要的是 myMap.getOrElse(x, y)
的等价物,如果键 x
不在地图中,
myMap
有默认值,则返回该值
否则返回y
一个人为的问题示例:
scala> def f(m: Map[String, String]) = m.getOrElse("hello", "world")
f: (m: Map[String,String])String
scala> val myMap = Map("a" -> "A").withDefaultValue("Z")
myMap: scala.collection.immutable.Map[String,String] = Map(a -> A)
scala> f(myMap)
res0: String = world
在这种情况下,我希望 res0
是 "Z"
而不是 "world"
,因为 myMap
是用它作为默认值定义的。但是getOrElse
不是这样工作的。
我可以使用m.apply
代替m.getOrElse
,但不保证映射具有默认值,因此它可能会引发异常(我可以捕获异常,但这并不理想)。
scala> def f(m: Map[String, String]) = try
| m("hello")
| catch
| case e: java.util.NoSuchElementException => "world"
|
f: (m: Map[String,String])String
scala> val myMap = Map("a" -> "A").withDefaultValue("Z")
myMap: scala.collection.immutable.Map[String,String] = Map(a -> A)
scala> f(myMap)
res0: String = Z
scala> val mapWithNoDefault = Map("a" -> "A")
mapWithNoDefault: scala.collection.immutable.Map[String,String] = Map(a -> A)
scala> f(mapWithNoDefault)
res1: String = world
以上产生了预期值,但看起来很混乱。我无法根据地图是否具有默认值进行模式匹配和调用apply
或getOrElse
,因为无论默认值如何,类型都是相同的(scala.collection.immutable.Map[String,String]
)。
有没有不涉及捕获异常的方法?
【问题讨论】:
【参考方案1】:可以检查地图是否为Map.WithDefault
的实例:
implicit class EnrichedMap[K, V](m: Map[K, V])
def getOrDefaultOrElse(k: K, v: => V) =
if (m.isInstanceOf[Map.WithDefault[K, V]]) m(k) else m.getOrElse(k, v)
然后:
scala> val myMap = Map("a" -> "A").withDefaultValue("Z")
myMap: scala.collection.immutable.Map[String,String] = Map(a -> A)
scala> myMap.getOrDefaultOrElse("hello", "world")
res11: String = Z
scala> val myDefaultlessMap = Map("a" -> "A")
myDefaultlessMap: scala.collection.immutable.Map[String,String] = Map(a -> A)
scala> myDefaultlessMap.getOrDefaultOrElse("hello", "world")
res12: String = world
这种反射是否比对非异常控制流使用异常更好是一个悬而未决的问题。
【讨论】:
哦,Map.WithDefault
正是我要找的。谢谢!
请注意,这仍然有点棘手——地图不是静态类型为WithDefault
,所以我们必须使用反射。这种反射不会造成显着的性能损失,但仍远非理想。【参考方案2】:
您可以使用 Try
代替 try/catch,这样看起来会更干净一些。
val m = Map(1 -> 2, 3 -> 4)
import scala.util.Try
Try(m(10)).getOrElse(0)
res0: Int = 0
val m = Map(1 -> 2, 3 -> 4).withDefaultValue(100)
Try(m(10)).getOrElse(0)
res1: Int = 100
【讨论】:
它看起来确实更好看!虽然我希望有一种方法可以让我不必在可能引发异常的情况下调用apply
(如果可能的话)
如果我错了,有人可能会纠正我,但看起来不可能。引发异常的是Map
的default
方法。如果只是它返回一个Option
,而不是。无论哪种方式,您仍然需要进行某种检查。以上是关于如何判断 Map 是不是有默认值?的主要内容,如果未能解决你的问题,请参考以下文章
在 Dart 中定义函数时,如何将参数的默认值设置为 ,即空 Map?
Groovy - 如何在不更新地图的情况下使用默认值获取地图值
postgresql 判断字段是不是为空 空给默认值 否则取该字段是啥函数来着?
java中数组变量名的默认值 如定义int[] a;此时a的默认值应该为null吧,如