Operating on the values in a map if the key meets a condition

3,391 views
Skip to first unread message

John

unread,
Apr 6, 2012, 6:30:01 PM4/6/12
to scala-user
I'm trying to operate on the values in a map. It's a classic mapValues
scenario with a slight wrinkle. I only want to update the values if
the key meets a boolean condition. Example:

val m = map(a -> 1, b -> 2)

m.mapValues( case (k, v) => if (k == "b") v+1 else v )

What I typed doesn't work, but I think you can see what I am trying to
do. Iterating over each pair, I'm checking to see if the key meets a
condition. If it does, I want to update that value. If it does not, I
just want to return the value unchanged.

This probably isn't too hard, but I can't figure it out. My data
structure is that of a map, so I do not have the flexibility to change
the input. I need to work with it as given and figure out how to solve
this.

Thanks!

John

unread,
Apr 6, 2012, 6:40:44 PM4/6/12
to scala-user
Never mind. I figured out what I was doing wrong. Thanks anyway!

Erik Post

unread,
Apr 8, 2012, 4:52:18 PM4/8/12
to scala...@googlegroups.com
Hi John,

There was a similar question on the list last week. Do you mean something like this?

  val m = Map("a" -> 1, "b" -> 2)  
  m.map { case ("b", v) => v+1 case (k,v) => v }

Cheers,
Erik

Lanny Ripple

unread,
Apr 8, 2012, 11:31:26 PM4/8/12
to scala-user
Since this is scala-user even though John has got his answer I'll
throw out what's going on in case it's helpful to anyone else.

The scala collection library tries to return a result of the same
"shape" as the original collection. (Hard enough that I can't ever
remember bumping into a corner case where it didn't but presumably if
you got really out there you could find one.) What this means is if
you map over a List you get back a List and over a Map you'd get back
a map. (If you want a new structure as a result it's much easier to
mess things up but google for "stackoverflow scala breakout" for the
gory details.)

Anyway John was mapping over a Map. Doing so hands a pair, Pair(key,
value), to your function. To get a map back from that the collections
library would really like you to work with it and return a Pair(key,
value) so it can update the map. The original example was only
returning an Int result. There are lots of ways to make this work but
in the spirit of the original

scala> Map("a" -> 1, "b" -> 2).map{case kv@(k,v) => if (k == "b") (k,v
+1) else kv}
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map(a ->
1, b -> 3)

Enjoy,
-ljr

Derek Williams

unread,
Apr 9, 2012, 12:03:44 AM4/9/12
to Lanny Ripple, scala-user
On Sun, Apr 8, 2012 at 9:31 PM, Lanny Ripple <la...@spotinfluence.com> wrote:
Anyway John was mapping over a Map.  Doing so hands a pair, Pair(key,
value), to your function.  To get a map back from that the collections
library would really like you to work with it and return a Pair(key,
value) so it can update the map.  The original example was only
returning an Int result.  There are lots of ways to make this work but
in the spirit of the original

In the original example he was using 'mapValues'. The mistake was that 'mapValues' only provides the value, and not the key, to the function provided. So using plain 'map' would indeed be the correct way to fix his code, but only returning an 'Int' result was not the reason his code failed.

--
Derek Williams

Lanny Ripple

unread,
Apr 9, 2012, 9:27:16 AM4/9/12
to scala-user
*snap* Well that's what I get for trying to post after a long day.
Thanks for the correction.

-ljr
Reply all
Reply to author
Forward
0 new messages