Reputation: 53826
Here is code I wrote to average coordinate values contained within the values of a Map :
val averaged = Map((2,10) -> List((2.0,11.0), (5.0,8.0)))
//> averaged : scala.collection.immutable.Map[(Int, Int),List[(Double, Double)
//| ]] = Map((2,10) -> List((2.0,11.0), (5.0,8.0)))
averaged.mapValues(m => {
val s1 = m.map(m => m._1).sum
val s2 = m.map(m => m._2).sum
(s1 / m.size , s2 / m.size)
}) //> res0: scala.collection.immutable.Map[(Int, Int),(Double, Double)] = Map((2,
//| 10) -> (3.5,9.5))
This code works as expected but the mapValues
function requires number of passes equals to length of the List. Is there a more idiomatic method of achieving same using Scala ?
Upvotes: 2
Views: 64
Reputation: 52681
If I'm understanding your question correctly, you are asking if it is possible to avoid the traversal of m
on each access. The mapValues
method returns a view of a Map, meaning that there will be repeated work on access. To avoid that, just use map
instead:
val averaged = Map((2, 10) -> List((2.0, 11.0), (5.0, 8.0)))
val result = averaged.map {
case (key, m) =>
val (s1, s2) = m.unzip
(s1.sum / m.size, s2.sum / m.size)
}
println(result)
// Map((2,10) -> (3.5,9.5))
Using unzip
additionally means that the code won't traverse m
more than once.
Upvotes: 1