2013-10-20 85 views
2

如何避免初始化(線5和6)在這裏?在scala中跳過散列(hash)的散列的初始化?

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" 

我試圖withDefaultValue一個簡單的例子,但很明顯,我沒有錯:

/*** 
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 
*/ 

回答

0

withDefault方法不會在這裏工作。 A Map創建此方式每次沒有密鑰時返回一張新地圖,因此撥打mymap("foo")("bar") = "ok"將爲臨時創建的地圖分配「ok」,但下次您撥打mymap("foo")("bar")時,mymap上不存在的"foo"密鑰將導致創建新地圖,其中不包含映射"foo" -> "bar"

相反,考慮創建一個匿名的地圖。我表明,只有1嵌套的解決方案:

‡ 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