0

Consider the following

val myMap: Map[String, List[Int]] = Map("a" -> List(1,2,3), 
                                        "b" -> List(4,5,6), 
                                        "d" -> List(7))

val possibleKeys: List[String] = List("c","a", "b", "e")

I would like to traverse the possible keys, and if the map contains one, traverse the map's values

The options I came up with are:

With a filter

 for {
    key <- possibleKeys
    if (myMap contains key)
    int <- myMap(key)
    r <- 0 to int
  } yield (r, int)    

With getOrElse

  for {
    key <- possibleKeys
    int <- myMap.getOrElse(key, Nil)
    r <- 0 to int
  } yield (r, int)

(Both return the same result:)

List((0,1), (1,1), (0,2), (1,2), (2,2), (0,3), (1,3), (2,3), (3,3), (0,4), (1,4), (2,4), (3,4), (4,4), (0,5), (1,5), (2,5), (3,5), (4,5), (5,5), (0,6), (1,6), (2,6), (3,6), (4,6), (5,6), (6,6))

Since I know Scala supports Options in for comprehensions, I was a bit surprised that this didn't work

for {
    key <- possibleKeys
    int <- myMap.get(key)
    r <- 0 to int //<-- compilation error
  } yield (r, int)

It complains about type mismatch; found : List[Int] required: Int

Which I vaguely understand why, but is there a way to make this work without the if clause or the getOrElse methods? (e.g. is there a way to get the myMap.get(key) version to work?)

Eran Medan
  • 41,875
  • 56
  • 175
  • 268
  • Out of curiosity, your code doesn't seem to match your description. What is the `r – Mysterious Dan Apr 30 '13 at 13:38
  • @MyseriousDan just to illustrate that I intend using the result as the input of some other iteration, the verbal description is incomplete, will fix the description, thanks – Eran Medan Apr 30 '13 at 14:00

2 Answers2

4

You are trying to mix incompatible types in your for comprehension. You can fix it by converting the option to a Seq by example.

for {
  key <- possibleKeys
  ints <- myMap.get(key).toSeq
  int <- ints
  r <- 0 to int
} yield (r, int)

There is a rather nice explanation of the problem in this very similar question here: Type Mismatch on Scala For Comprehension.

Community
  • 1
  • 1
Régis Jean-Gilles
  • 31,374
  • 4
  • 75
  • 92
0

You can make use of the methods keySet and apply on Map

for {
  key <- possibleKeys
  if myMap.keySet(key)
  int <- myMap(key)
  r <- 0 to int
} yield (r, int)

res5: List[(Int, Int)] = List((0,1), (1,1), (0,2), (1,2), (2,2), (0,3), (1,3), (2,3), (3,3), (0,4), (1,4), (2,4), (3,4), (4,4), (0,5), (1,5), (2,5), (3,5), (4,5), (5,5), (0,6), (1,6), (2,6), (3,6), (4,6), (5,6), (6,6))
pagoda_5b
  • 7,007
  • 1
  • 24
  • 37