2

I'm trying to update the value in a map[String, WordCount] while iterating this

case class WordCount(name: String,
                 id: Int,
                 var count: Double,
                 var links: scala.collection.mutable.HashMap[String, Double],
                 var ent: Double) {

    def withEnt(v: Double): WordCount = {println(s"v: $v"); copy(ent = v)}
}

var targets = mutable.HashMap[String, WordCount]()

The function calEnt is:

def calEnt(total: Double, links: scala.collection.mutable.HashMap[String, Double]): Double = {
    var p: Double = 0.0
    var ent: Double = 0.0
    links.map(d => {
      p = d._2 / total
      ent -= p * Math.log(p)
    })
    return ent
  }

And I'm using:

targets.map(m => m._2.withEnt(calEnt(m._2.count, m._2.links)))

for iterating the map and calculate the new value for ent and update this with withEnt. I can imprime in console the new value but it is not setting inside the map. What is the way to do that? please.

lantis
  • 349
  • 1
  • 4
  • 10
  • 1
    It is almost **never** meaningful to have a mutable data structure in a `var` — either use a `val` with a mutable data structure, or a `var` with an immutable one; also, note that it's generally preferrable and safer to use a `var`+immutable; see http://stackoverflow.com/questions/11386559/val-mutable-versus-var-immutable-in-scala – Erik Kaplun Oct 28 '14 at 20:45

2 Answers2

9

Use foreach:

targets.foreach(m => targets(m._1) = m._2.withEnt(calEnt(m._2.count, m._2.links)))

Self-contained example:

val m = scala.collection.mutable.HashMap[Int, Int](1 -> 1, 2 -> 2)
println(m)
m.foreach(p => m(p._1) = p._2 + 1)
println(m)
jonderry
  • 23,013
  • 32
  • 104
  • 171
  • Thanks!!! Sorry but I have not enough reputation to vote up your answer as useful, but really it is useful – lantis Oct 28 '14 at 20:37
3

map method won't modify your targets HashMap. It will return a new, modified HashMap. Try this:

targets = targets.map(m => (m._1, m._2.withEnt(calEnt(m._2.count, m._2.links))))

Note also that we map to a pairs of keys m._1 and modified values. Not just to values.

Anatoliy Kmetyuk
  • 708
  • 1
  • 6
  • 10
  • I get it, then how should I do just to update the value without creating a new HashMap? – lantis Oct 28 '14 at 20:22
  • Just iterate over all the keys and update their values. `targets.keys` will return the keys. So you go somehow as follows: `for (k <- targets.keys) targets(k) = /* your new value */`. – Anatoliy Kmetyuk Oct 28 '14 at 20:30
  • It would look much nicer with tuple unpacking as in `targets.map { case (k, v) => ... }` instead of `m._1` and `m._2`. – Erik Kaplun Oct 28 '14 at 20:43