Scala 如何访问和更新地图的可变地图中的值
我有一个三级数据结构(缩进和换行以提高可读性): 访问最里面的数据(分数)需要大量键入:Scala 如何访问和更新地图的可变地图中的值,scala,map,scala-2.8,scala-collections,Scala,Map,Scala 2.8,Scala Collections,我有一个三级数据结构(缩进和换行以提高可读性): 访问最里面的数据(分数)需要大量键入: import org.scalatest.{Assertions, FunSuite} class MapExamplesSO extends FunSuite with Assertions { test("Update values in a mutable map of map of maps") { import scala.collection.mutable.Map //
import org.scalatest.{Assertions, FunSuite}
class MapExamplesSO extends FunSuite with Assertions {
test("Update values in a mutable map of map of maps") {
import scala.collection.mutable.Map
// The m map is essentially an accumulator
val m = Map("normal" ->
Map("home" -> Map("wins" -> 0, "scores" -> 0),
"away" -> Map("wins" -> 0, "scores" -> 0)
)
)
//
// Is there a less verbose way to increment the scores ?
//
assert(m("normal").apply("home").apply("scores") === 0)
val s1 = m("normal").apply("home").apply("scores") + 1
m("normal").apply("home").update("scores", s1)
assert(m("normal").apply("home").apply("scores") === 1)
val s2 = m("normal").apply("home").apply("scores") + 2
m("normal").apply("home").update("scores", s2)
assert(m("normal").apply("home").apply("scores") === 3)
}
}
是否有一种不那么冗长的方法来修改分数的值
我是一名Scala新手,因此对上述代码的所有其他观察也都是受欢迎的。您不必使用“apply”,只需使用“()”正常执行即可
你可以写
m("normal").apply("home").apply("scores")
作为
然而,我不确定这样的结构是否是一个好主意。也许你应该考虑把这个功能封装在一个专门的类中。添加一个本地助手函数总是减少代码复制的好方法:
class MapExamplesSO {
def test {
import scala.collection.mutable.Map
// The m map is essentially an accumulator
var m = Map("normal" ->
Map("home" -> Map("wins" -> 0, "scores" -> 0),
"away" -> Map("wins" -> 0, "scores" -> 0)))
//Local Helper returns (Old, New)
def updateScore(k1 : String,k2 : String,k3 : String)
(f : Int => Int) : (Int, Int) = {
val old = m(k1)(k2)(k3)
m(k1)(k2)(k3) = f(old)
(old, m(k1)(k2)(k3))
}
assert(m("normal")(home")("scores") === 0)
assert(updateScore("normal","home","scores")(_+1)._2 === 1)
assert(updateScore("normal","home","scores")(_+2)._2 === 3)
}
}
[编辑使代码更紧凑]更不冗长:
assert(m("normal")("home")("scores") === 0)
val s1 = m("normal")("home")("scores") + 1
m("normal")("home")("scores") = s1
assert(m("normal")("home")("scores") === 1)
val s2 = m("normal")("home")("scores") + 2
m("normal")("home")("scores") = s2
assert(m("normal")("home")("scores") === 3)
这充分利用了apply
和update
都具有如上所示的语法优势。更简短的是:
// On REPL, put both these definitions inside an object instead
// of entering them on different lines
def scores = m("normal")("home")("scores")
def scores_=(n: Int) = m("normal")("home")("scores") = n
assert(scores === 0)
val s1 = scores + 1
scores = s1
assert(scores === 1)
val s2 = scores + 2
scores = s2
// Just so you see these updates are being made to the map:
assert(m("normal")("home")("scores") === 3)
它利用了getter和setter的语法优势
(getter定义必须存在,setter定义才能工作)。聪明!(我只是希望不要太聪明:)在我意识到这里发生了什么之前,我读了几本书。回答得很好,谢谢!这也是一个非常有用的答案-谢谢!我也希望你投更多的票。Getter/setter为初学者解释说:在本例中,这是可行的,但如果m(“normal”)(“home”)尚未定义,则将不起作用。
class MapExamplesSO {
def test {
import scala.collection.mutable.Map
// The m map is essentially an accumulator
var m = Map("normal" ->
Map("home" -> Map("wins" -> 0, "scores" -> 0),
"away" -> Map("wins" -> 0, "scores" -> 0)))
//Local Helper returns (Old, New)
def updateScore(k1 : String,k2 : String,k3 : String)
(f : Int => Int) : (Int, Int) = {
val old = m(k1)(k2)(k3)
m(k1)(k2)(k3) = f(old)
(old, m(k1)(k2)(k3))
}
assert(m("normal")(home")("scores") === 0)
assert(updateScore("normal","home","scores")(_+1)._2 === 1)
assert(updateScore("normal","home","scores")(_+2)._2 === 3)
}
}
assert(m("normal")("home")("scores") === 0)
val s1 = m("normal")("home")("scores") + 1
m("normal")("home")("scores") = s1
assert(m("normal")("home")("scores") === 1)
val s2 = m("normal")("home")("scores") + 2
m("normal")("home")("scores") = s2
assert(m("normal")("home")("scores") === 3)
// On REPL, put both these definitions inside an object instead
// of entering them on different lines
def scores = m("normal")("home")("scores")
def scores_=(n: Int) = m("normal")("home")("scores") = n
assert(scores === 0)
val s1 = scores + 1
scores = s1
assert(scores === 1)
val s2 = scores + 2
scores = s2
// Just so you see these updates are being made to the map:
assert(m("normal")("home")("scores") === 3)