访问地图内部地图和处理可能的异常的有效方法
Efficient way to access maps inside maps and handle possible exceptions
我有一张根据 JSON 构建的地图,它有一些层次结构。例如:
"2015-05": {
"129557": {
"123456": 3,
"654321": 2,
"143526": 1
}
}
这存储为嵌套地图。我想要一个简单的方法来访问密钥。我可以对每个键进行多次检查,然后查看它是否存在,然后对第二个键进行检查,依此类推。然而,这似乎很麻烦。相反,我选择做这样的事情:
def getNumFromMap(key1: String, key2: Int, key3: String): Option[Int] ={
try{
map(key1)(key2).get(key3)
}catch{
case e: Exception => None
}
}
此函数可能会执行数百万次。使用 try/catch 会减慢执行速度吗?有没有更快的更好的方法来完成同样的事情?
使用 for 表达式怎么样?
def getNumFromMap(key1: String, key2: Int, key3: String): Option[Int] ={
for {
m1 <- map.get(1)
m2 <- m1.get(2)
m3 <- m2.get(3)
} yield m3
}
但是,如果不正确衡量,很难说哪种方法更快。
使用 a 进行理解:
type MMMap[K1, K2, K3, V] = Map[K1, Map[K2, Map[K3, V]]]
def getFromMMMap[K1, K2, K3, V](
mmmap: MMMap[K1, K2, K3, V], k1: K1, k2: K2, k3: K3
) : Option[V] =
for {
mmap <- mmmap.get(k1)
map <- mmap.get(k2)
v <- map.get(k3)
} yield v
对于 MMMap[String, Int, String, Int]
:
val mmmap = Map ("a" -> Map(1 -> Map("b" -> 2)))
scala> getFromMMMap(mmmap, "a", 1, "b")
res7: Option[Int] = Some(2)
def getNumFromMap(m: Map[String, Map[Int, Map[String, Int]]], key1: String, key2: Int, key3: String): Option[Int] = {
m.get(key1).flatMap(_.get(key2)).flatMap(_.get(key3))
}
或者,单行版本:
def get3[A, B, C, V](m: Map[A,Map[B,Map[C,V]]], a:A, b:B, c:C) : Option[V] =
m.get(a).flatMap(_.get(b).flatMap(_.get(c)))
或者只是为了好玩,皮条客版本
implicit final class Map3[A,B,C,V](val self : Map[A,Map[B,Map[C,V]]]) extends AnyVal {
def get3(a:A, b:B, c:C) : Option[V] =
self.get(a).flatMap(_.get(b).flatMap(_.get(c)))
}
然后:
val m : Map[Int, Map[String, Map[Boolean, Char]]] = Map(5 -> Map("a" -> Map(true -> 'c')))
m.get3(5, "a", true)
我有一张根据 JSON 构建的地图,它有一些层次结构。例如:
"2015-05": {
"129557": {
"123456": 3,
"654321": 2,
"143526": 1
}
}
这存储为嵌套地图。我想要一个简单的方法来访问密钥。我可以对每个键进行多次检查,然后查看它是否存在,然后对第二个键进行检查,依此类推。然而,这似乎很麻烦。相反,我选择做这样的事情:
def getNumFromMap(key1: String, key2: Int, key3: String): Option[Int] ={
try{
map(key1)(key2).get(key3)
}catch{
case e: Exception => None
}
}
此函数可能会执行数百万次。使用 try/catch 会减慢执行速度吗?有没有更快的更好的方法来完成同样的事情?
使用 for 表达式怎么样?
def getNumFromMap(key1: String, key2: Int, key3: String): Option[Int] ={
for {
m1 <- map.get(1)
m2 <- m1.get(2)
m3 <- m2.get(3)
} yield m3
}
但是,如果不正确衡量,很难说哪种方法更快。
使用 a 进行理解:
type MMMap[K1, K2, K3, V] = Map[K1, Map[K2, Map[K3, V]]]
def getFromMMMap[K1, K2, K3, V](
mmmap: MMMap[K1, K2, K3, V], k1: K1, k2: K2, k3: K3
) : Option[V] =
for {
mmap <- mmmap.get(k1)
map <- mmap.get(k2)
v <- map.get(k3)
} yield v
对于 MMMap[String, Int, String, Int]
:
val mmmap = Map ("a" -> Map(1 -> Map("b" -> 2)))
scala> getFromMMMap(mmmap, "a", 1, "b")
res7: Option[Int] = Some(2)
def getNumFromMap(m: Map[String, Map[Int, Map[String, Int]]], key1: String, key2: Int, key3: String): Option[Int] = {
m.get(key1).flatMap(_.get(key2)).flatMap(_.get(key3))
}
或者,单行版本:
def get3[A, B, C, V](m: Map[A,Map[B,Map[C,V]]], a:A, b:B, c:C) : Option[V] =
m.get(a).flatMap(_.get(b).flatMap(_.get(c)))
或者只是为了好玩,皮条客版本
implicit final class Map3[A,B,C,V](val self : Map[A,Map[B,Map[C,V]]]) extends AnyVal {
def get3(a:A, b:B, c:C) : Option[V] =
self.get(a).flatMap(_.get(b).flatMap(_.get(c)))
}
然后:
val m : Map[Int, Map[String, Map[Boolean, Char]]] = Map(5 -> Map("a" -> Map(true -> 'c')))
m.get3(5, "a", true)