我有一个三级数据结构(缩进和换行符以便于阅读):
scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map
scala> val m = Map("normal" -> Map("home" -> Map("wins" -> 0, "scores" -> 0),
"away" -> Map("wins" -> 0, "scores" -> 0)))
m: scala.collection.mutable.Map[java.lang.String,
scala.collection.mutable.Map[java.lang.String,
scala.collection.mutable.Map[java.lang.String,Int]]] =
Map((normal,Map(away -> Map(wins -> 0, scores -> 0),
home -> Map(wins -> 0, scores -> 0))))
访问最里面的数据(分数)需要大量输入:
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新手,所以对上述代码的所有其他观察结果也是受欢迎的。
答案 0 :(得分:21)
您不必使用“apply”,只需使用“()”
即可m("normal")("home")("scores") = 1
答案 1 :(得分:10)
你可以写
m("normal").apply("home").apply("scores")
作为
m("normal")("home")("scores")
但是我不确定这样的结构是不是一个好主意。也许您应该考虑将此功能封装在专门的类中。
答案 2 :(得分:3)
添加本地帮助函数始终是减少代码重复的好方法:
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)
}
}
[编辑代码更紧]
答案 3 :(得分: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定义生效)。