knub
knub

Reputation: 4032

Multi-key Map in Scala

How can I create a Map in Scala which does not only take a single parameter as key, but rather two or three.

val map = //..?
map("abc", 1) = 1
println(map("abc", 2)) // => null
println(map("abc", 1)) // => 1

I tried using tuples as a key, but then I have to assign values like this

map(("abc", 1)) = 1

Can I somehow get rid of the inner parentheses?

Upvotes: 6

Views: 9185

Answers (4)

user3282611
user3282611

Reputation: 920

I got compiling errors using Luigi Plinge's approach. The following approach works for me, which is simpler.

scala> var b = Map[(Int, Int), Int]()
b: scala.collection.mutable.Map[(Int, Int),Int] = Map()

scala> b = b + ((1,1)->2)
b: scala.collection.mutable.Map[(Int, Int),Int] = Map((1,1) -> 2)

scala> b
res15: scala.collection.mutable.Map[(Int, Int),Int] = Map((1,1) -> 2)

scala> b = b + ((1,2)->2)
b: scala.collection.mutable.Map[(Int, Int),Int] = Map((1,1) -> 2, (1,2) -> 2)

scala> b(1,1)
res16: Int = 2

scala> b(1,2)
res17: Int = 2

Upvotes: 1

Felix Trepanier
Felix Trepanier

Reputation: 346

You could also use

map += ("abc", 1) -> 1

If the map key represents something (e.g. user info) and if you want to add clarity to your code (especially if you have 3 elements in the key), I would go with a case class as the key. Case classes have equals and hashcode implemented so you can safely use them as keys in a map. The code would be more verbose though:

case class MapKey(s: String, i: Int, d: Double)

val map = Map[MapKey, X](MapKey("a", 1, 1.1) -> "value1", MapKey("b", 2, 2.2) -> "value2")

val map2 = map + (MapKey("c", 3, 3.3) -> "value3")

//or for mutable map
map(MapKey("d", 4, 4.4)) = "value4"
//or
map += MapKey("e", 5, 5.5) -> "value5"

Upvotes: 12

Luigi Plinge
Luigi Plinge

Reputation: 51099

You can add your own enhancement to Map that will do the trick:

import collection.mutable.Map

implicit class EnhancedMap[A,B,C](m: Map[(A,B),C]) {
  def update(a: A, b: B, c: C) { m((a,b)) = c }
}

then

val map = Map(("abc", 1) -> 0)
map("abc", 1) = 1

works just fine.

Upvotes: 7

om-nom-nom
om-nom-nom

Reputation: 62835

You can use -> syntax for tuples:

map("abc" -> 1) = 1

Upvotes: 3

Related Questions