Reputation: 3689
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
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
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
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