Teodorico Levoff
Teodorico Levoff

Reputation: 1659

Scala: How to return the key that contains an item in their value where value is a Set?

I have a Map[Int, Set[Int]]and given an item I want to return the key that indexes to the Set where item exists in. For example if I have a Map(1 -> Set("a"), 2 -> Set("b"), 3 -> Set("c","z")). Say the item is "z" I want to return 3 because 3 is the key that indexes to the set that contains 3. Here is what I currently have, but I can't seem to find a good way to get the key. I can only get the value, the Set[Int]. Assume the item will only be in one possible set.

def find(djs: Map[Int, Set[Int]], item: Int) :Int = {
for ((key, set) <- djs) {
  if (set.contains(item)) {
    key
  } 
}

Upvotes: 0

Views: 440

Answers (3)

The Archetypal Paul
The Archetypal Paul

Reputation: 41749

collectFirst is made for this:

val m = Map(1 -> Set("a"), 2 -> Set("b"), 3 -> Set("c","z"))

m.collectFirst{case (k,v) if v.contains("z") => k}
//> res0: Option[Int] = Some(3)

and I always forget Set can be used as a function itself (i.e. apply is the same as contains)

m.collectFirst{case (k,v) if v("z") => k}
//> res0: Option[Int] = Some(3)

Upvotes: 2

soote
soote

Reputation: 3260

The find operator can work well here:

def find[A, B](m: Map[A, Set[B]], item: B): Option[A] = 
    m.find { case (key, set) => set.contains(item) }
     .map  { case (key, set) => key }

Upvotes: 2

jwvh
jwvh

Reputation: 51271

If you need to return one or None then Option[] would be the way to go. If returning one, many, or none is required then returning a List[] might be in order.

val m = Map(1 -> Set("a"), 2 -> Set("b"), 3 -> Set("c","z"))

m.flatMap{ case (k,vs) => if (vs.contains("z")) Seq(k) else Seq() }  // List(3)
m.flatMap{ case (k,vs) => if (vs.contains("w")) Seq(k) else Seq() }  // List()

Upvotes: 2

Related Questions