【问题标题】:Scala attribution to a default mapScala 归因于默认地图
【发布时间】:2014-02-05 06:59:40
【问题描述】:

我正在尝试理解this answer,与使用默认值的地图有关:

val lists = new mutable.HashMap[String,List[Int]].withDefaultValue(Nil)

lists("dog") ::= 13
lists("cat") ::= 14
lists("dog") ::= 15  //(13, 15)

据我了解,scala 使用“嵌套”函数来表示不可变列表。一个不幸的副作用是迭代不可变列表以 reverse order 返回元素。

为避免顺序相反,我尝试使用 ArrayBuffer 来实现:

val lists = new mutable.HashMap[String,mutable.ArrayBuffer[Int]].withDefault(_=>ArrayBuffer())

lists("dog").append(1)
println( lists("dog") ) //prints "ArrayBuffer()"

很遗憾,这不起作用。看来scala实际上并没有默认值放回地图上,而是一直返回空的ArrayBuffers

最后,我使用了以下代码:

val lists1 = new mutable.HashMap[String,mutable.ArrayBuffer[Int]]
val lists= lists1.withDefault( x=>{val n= mutable.ArrayBuffer[Int](); lists1(x)=n; n})

这可行,但似乎不必要地复杂。有没有更好的解决方案?

【问题讨论】:

    标签: scala map default


    【解决方案1】:

    ::= 的实际工作原理有点不明显。它使用列表中的指定函数::(前置),然后将函数的结果(=)分配回指定键下的映射。

    如果您想要快速追加,不仅要预先添加,而且还要在映射中使用不可变集合作为值,请使用 Vector

    val map = mutable.Map[String, Vector[Int]]().withDefaultValue(Vector())
    

    现在,Vector:+ method,它返回一个附加元素的向量的副本,这是完美的。这意味着,当您考虑::= 的解释时,您可以这样做:

    map("dog") :+= 7
    map("cat") :+= 3
    map("dog") :+= 11
    

    结果:

    scala> map("cat")
    res4: Vector[Int] = Vector(3)
    
    scala> map("dog")
    res5: Vector[Int] = Vector(7, 11)
    

    【讨论】:

    • 当我意识到::=+= 运算符一样工作时,我发现它更容易理解。 a::=b 转换为 a=a::b,就像 a+=b 转换为 a=a+b。感谢Vector 的提示,它看起来正是我想要的
    • 如果我仍然想使用 ArrayBuffer(可变)而不是 Vector(不可变)怎么办?
    • @ostefano 然后你必须改变一些点点滴滴,从地图定义开始:val map = mutable.Map[String, mutable.ArrayBuffer[Int]]().withDefault(_ => mutable.ArrayBuffer()),然后更新:map("dog") +== 7
    猜你喜欢
    • 2012-04-08
    • 2016-06-05
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    相关资源
    最近更新 更多