Core_Dumped
Core_Dumped

Reputation: 4699

Using find function for maps in scala

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?

Upvotes: 15

Views: 24242

Answers (4)

warrens
warrens

Reputation: 2105

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>

Upvotes: 0

kungfushark
kungfushark

Reputation: 23

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.

Upvotes: 1

mikołak
mikołak

Reputation: 9705

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

Upvotes: 20

Brian
Brian

Reputation: 20285

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)

Upvotes: 2

Related Questions