简体   繁体   中英

Skip initialization of hash of hash (of hash) in scala?

How do I avoid the initialization (lines 5 and 6) here?

import scala.collection._
def newHash = mutable.Map[String,String]()
def newHoH = mutable.Map[String,mutable.Map[String,String]]()
var foo = mutable.Map[String,mutable.Map[String,mutable.Map[String,String]]]()
foo("bar") = newHoH          //line 5
foo("bar")("baz") = newHash  //line 6
foo("bar")("baz")("whee") = "duh"

I tried withDefaultValue with a simpler example but obviously I did it wrong:

/***
scala> var foo = mutable.Map[String,mutable.Map[String,String]]().withDefaultValue(mutable.Map(""->""))
foo: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]] = Map()

scala> foo("bar")("baz") = "duh"
scala> foo("b")("baz") = "der"
scala> foo("bar")("baz")
res7: String = der
*/

The withDefault method won't work here. A Map created this way returns a new map everytime there is no key, so calling mymap("foo")("bar") = "ok" will assign "ok" into a temporarily created map, but the next time you call mymap("foo")("bar") , a non-existent "foo" key on mymap will result in creating a new map, which will not contain the mapping "foo" -> "bar" .

Instead, consider creating an anonymous map. I show a solution with only 1 nestings:

‡ scala-version 2.10.1
Welcome to Scala version 2.10.1 (Java HotSpot(TM) Server VM, Java 1.7.0_21).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import collection._
import collection._

scala> :paste
// Entering paste mode (ctrl-D to finish)

def newHash = mutable.Map[String,String]().withDefault(_ => "")

def newHoH = new mutable.Map[String,mutable.Map[String,String]]() {
  val m = mutable.Map[String, mutable.Map[String, String]]()
  def +=(kv: (String, mutable.Map[String, String])) = { m += kv; this }
  def -=(k: String) = { m -= k; this }
  def get(k: String) = m.get(k) match {
    case opt @ Some(v) => opt
    case None =>
      val v = newHash
      m(k) = v
      Some(v)
  }
  def iterator = m.iterator
}

// Exiting paste mode, now interpreting.

newHash: scala.collection.mutable.Map[String,String]
newHoH: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]{val m: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]}

scala> val m = newHoH
m: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]{val m: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]} = Map()

scala> m("foo")("bar") = "ok"

scala> m("foo")("bar")
res1: String = ok

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM