Ashiqur Rahman
Ashiqur Rahman

Reputation: 29

Scala how to get the key of Map where value as List

I have Map like this:

val myMap = Map(
    testKey1 -> List(testValue1, testValue2, testValue3....), 
    testKey2 -> List(testValue4, testValue5, testValue6....),
    testKey3 -> List(testValue7, testValue8, testValue9....)
)

I want to do some exact matching of the list value and get the corresponding key of map.

Like example: I want to check if 'testValue9' is in this Map then I will get the key 'testKey3'.

I think it could be solvable by this way but I can't iterate through list's value to check the value is there or not. Or could someone please give me some hints.

myMap foreach {
          case (key, List(_)) => println( key )
          case _ =>    
        }

Upvotes: 1

Views: 3886

Answers (4)

Tim
Tim

Reputation: 27356

If you are trying to find a single value in a Map you can use find:

  myMap.find(_._2.contains(value)).map(_._1)

This will return Some(key) if the value is found, otherwise None.

If you think there may be multiple matching values, you can replace find with filter

  myMap.filter(_._2.contains(value)).map(_._1)

or use collect

  myMap.collect{ case (k, v) if v.contains(value) =>  k }

In both cases this will return a list of all matching keys and will depend on how Map is implemented.

Note that the filter option can be expressed using a for expression, which does exactly the same thing:

  for { (k,v) <- myMap if v.contains(value) } yield k

In most cases it is just a question of style as to which is better, though the collect is likely to perform best.

Update

Raman Mishra helpfully points out that the filter version can be simplified to

myMap.filter(_._2.contains(value)).keys

This returns Set rather than List which is more appropriate because the order is not significant.

Upvotes: 3

Raman Mishra
Raman Mishra

Reputation: 2686

you want to do this i think:

Assuming Key is String and the value is List[String]

val keyContainsValue: immutable.Iterable[String] = myMap map {
    case (key, value) => if (value.contains(testValue9)) key else ""
  }

you can use empty string as the defalut value so that you can get the return type as iterable[String].

As i don't know the type of your key and value you can use option too. For that purpose like this.

val keyContainsValue: immutable.Iterable[Option[String]] = myMap map {
        case (key, value) => if (value.contains(testValue9)) Some(key) else None
      }
println(keyContainsValue.flatten) //you will get the list of keys which contains the value specified.

Upvotes: 3

Terry Dactyl
Terry Dactyl

Reputation: 1868

val searchValue = "testValue9"

myMap.collect{ case (key, values) if values.contains(searchValue) => key }

Upvotes: 1

Arnon Rotem-Gal-Oz
Arnon Rotem-Gal-Oz

Reputation: 25909

you can do something like

val getKeys = (k: String) => for (m<- myMap.keys;
                                 v<- myMap(m);
                                 if v==k) yield m

Upvotes: 0

Related Questions