15

I am trying to find a key in a Map, given a value. I am using the 'find' function by not able to figure out the right predicate for it:

val colors = Map(1 -> "red", 2 -> "blue")
def keyForValue(map: Map[Int, String], value: String) = {
    val bool = map.find{map.foreach{map.values(i) == value}}
        bool.key
  }

How do I iterate over the map and find the key when I know the value?

4 Answers 4

20

You use the same kind of predicate as with a List, but keep in mind you're evaluating it over (key,value) pairs, instead of just values (and getting a pair back as well!).

Simple example:

val default = (-1,"")
val value = "red"
colors.find(_._2==value).getOrElse(default)._1
Sign up to request clarification or add additional context in comments.

2 Comments

It returns a Some(1, "red"). Can I extract the key from it?
@Core_Dumped : I assume from the accept that you've probably already figured it out, but just in case: if you run the code as it actually is in the answer, you'll get the key. This is what .getOrElse(default)._1 is for. It extracts the value from the Option you get from find, given a default, and with _1 you get the first element of the resulting pair, which happens to be the key in the case of maps.
2

The signature for find in Map is find(p: ((A, B)) ⇒ Boolean): Option[(A, B)]. So the predicate takes a Tuple2 and must return a Boolean. Note I changed value to an Int since the key in colors is also an Int.

scala> def keyForValue(map: Map[Int, String], value: Int) = {
     | colors.find({case (a,b) => a  == value})
     | }
keyForValue: (map: Map[Int,String], value: Int)Option[(Int, String)]

Test:

scala> keyForValue(colors, 1)
res0: Option[(Int, String)] = Some((1,red))

You can also use get:

scala> colors.get(1)
res1: Option[String] = Some(red)

Comments

1

You can always go with the abstract solution and swap the keys with their values, store it in a new map, and then search the new map:

val colors = Map(1 -> "red", 2 -> "blue")
def keyForValue(map: Map[Int, String], value: String) = {
  val revMap = map map {_.swap}
  val key = revMap(value)
  key
}

The third line swaps the keys with their values, and stores it in revMap. (map map means the name of the map, in this case, the parameter, map, then the word map, then {_.swap} to actually swap the keys with their values.

Comments

0

I would avoid passing the map to the find method, and rather pass only the map's keys to the find method.

This avoids dealing with an Option[Int,String] -- instead it is Option[Int].

// sample data
val colors = Map(1 -> "red", 2 -> "blue", 3 -> "yellow")

// function you need
def keyForValue(theMap: Map[Int, String], theValue: String): Int = {

    val someKey = theMap.keys.find( k => theMap(k) == theValue )
    someKey match {
        case Some(key) => {
            println(s"the map contains ${key} -> ${theValue}")
            return key
        }
        case None => {
            println(s"a key was not found for ${theValue}")
            return -1
        }
    }
}

This gives:

scala> val result = keyForValue( colors, "blue" )
the map contains 2 -> blue
result: Int = 2

scala>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.