Scala:更改地图内列表中的值

时间:2017-06-07 17:15:39

标签: scala list dictionary

我遇到了一个问题: 我想改变一个元素,但代码正在改变所有元素。 我一定做错了什么。 这就是我所拥有的:

var critics: Map[String, List[(String, Double)]] = Map(
  "First" -> List(("a", 1.0), ("b", 2.0)),
  "Second" -> List(("c", 3.0), ("d", 4.0))
  )

  def setNewRating(keyMap: String, param1: String, newRating: Double) = {
    val newList = critics(keyMap).map{case (param1, _) => (param1, newRating); case x => x}
    critics = critics + (keyMap -> newList)
    }

    println(critics)

    setNewRating("First", "b", 5.0)

    println(critics)

所以,我正在寻找关键字“First”并获取List我希望将“b”从2.0更改为5.0但是我得到的结果是:

critics: Map[String,List[(String, Double)]] = Map(First -> List((a,1.0), (b,2.0)), Second -> List((c,3.0), (d,4.0)))
setNewRating: (keyMap: String, param1: String, newRating: Double)Unit
Map(First -> List((a,1.0), (b,2.0)), Second -> List((c,3.0), (d,4.0)))
Map(First -> List((a,5.0), (b,5.0)), Second -> List((c,3.0), (d,4.0)))

代码更改了所有值!

提前感谢,

3 个答案:

答案 0 :(得分:1)

这应该有效。您在case子句param1中使用的.map{case (param1, _)与参数中定义的变量param1不同。它是一个新变量param1,它被赋予隐藏方法参数的Tuple2的第一个元素的值。

def setNewRating(keyMap: String, param1: String, newRating: Double) = {
  val newList = critics(keyMap) map {
    case (x, _) if x == param1 => (param1, newRating)
    case x => x
  }
  critics = critics + (keyMap -> newList)
}

答案 1 :(得分:1)

您需要将param1放入反引号中:

  def setNewRating(keyMap: String, param1: String, newRating: Double) = {
    val newList = critics(keyMap)
     .map { 
       case (`param1`, _) => param1 -> newRating 
       case x => x
     }
     critics = critics + (keyMap -> newList)
  }

问题是case (param1, _)表示“匹配任何内容,并将值存储到新的本地变量param1”。那不是你想要的。

 case (`param1`, _) => 

另一方面,表示“匹配与外部变量param1相同的值”。

或者,如果您将param1重命名为Param1,它也会起作用(显然,scala匹配假定以大写字母开头的所有内容都是常量)。我并不是建议你这样做,只是提到完整性。只需使用反引号。

(另外,使用这样的var让我感到畏缩,你真的应该找到一种方法来避免它,但这不是你的问题......)

答案 2 :(得分:0)

如果您愿意从List更改为Set,则可能只是缺少MultiMap特质。

  

可变映射的特征,其中多个值分配给键。

     

此类通常用作mixin。它将地图A到Set [B]对象的地图转换为将A映射到B对象的多重映射。

您可以找到参考here