Giora Simchoni
Giora Simchoni

Reputation: 3689

How to get a scala Map value, when the key is a tuple in which only the first element is known?

Suppose I have a scala immutable Map[(String, Boolean), Set[String]], e.g.:

val myMap = Map(("a",true) -> Set("b","c"))

Now suppose I only know the first element of the key tuple, "a". Can (and how if yes) I get the map's value for this key if:

1) I know that the key could either be ("a", true) or ("a", false) (there cannot be two keys with the same String as the first element)

2) I don't know that, in which case I wish to get some kind of concatenation on the possible two values, such as v1.union(v2) or v1 ++ v2, etc.

Is there any scala "magic" I could use, like myMap.get(("a", Any))?

Upvotes: 4

Views: 7722

Answers (3)

Alexey Romanov
Alexey Romanov

Reputation: 170723

If you have many queries like that, it could be a good idea to replace the map with Map[String, Map[Boolean, Set[String]]. It should be easy to see they are equivalent: when you have e.g. ("a", false) -> Set() and ("a", true) -> Set("a") in your original map, you'll have "a" -> Map(false -> Set(), true -> Set("a")) in the new one.

It is likely to be less memory-efficient, however, especially with these key types. You could improve this by replacing Map[Boolean, Set[String]] with (Option[Set[String]], Option[Set[String]]), where the first field corresponds to false and the second one to true.

In the case

1) I know that the key could either be ("a", true) or ("a", false) (there cannot be two keys with the same String as the first element)

just use Map[String, (Boolean, Set[String])].

Upvotes: 3

ka4eli
ka4eli

Reputation: 5424

myMap.collect {
  case (("a",b), s) => s
}.toSet.flatten

UPDATED (view comments):

If the myMap is rather large you can try:

Set(myMap.get("a", true), myMap.get("a", false)).flatten.flatten

Upvotes: 6

om-nom-nom
om-nom-nom

Reputation: 62835

In general, hash maps does not work like that, at least efficiently -- you still can scan map linearly and pick first key that matches criteria. In your particular case you can simply try to lookup record twice -- first with (key, true), then if nothing is found (key, false)

Upvotes: 9

Related Questions