1

I want to convert a Set to a Map, something like:

val x: Set[String] = Set("asds", "reqrq", "dadas")
x.fold(Map.empty[String, String]) { 
  (p: Map[String, String], q: String) => p + (q ->  doSomething(q)) 
}

But I get the following error:

type mismatch;
 found   : (Map[String,String], String) => scala.collection.immutable.Map[String,String]
 required: (Object, Object) => Object
val res16 = x.fold(Map.empty[String, String]) { (p: Map[String, String], q: String) => p + (q ->  doSomething(q)) }
                                                                                    ^

How does one elegantly achieve this?

Martinffx
  • 2,426
  • 4
  • 33
  • 60

2 Answers2

3

You don't need any folds, just use map on the Set, and then convert the result toMap. Here is an example where doSomething is _.toUpperCase:

Set("a", "b").map(x => x -> x.toUpperCase).toMap

If you want to avoid building an intermediate set, you can use breakOut to do everything in a single step:

val y: Map[String, String] = 
  Set("a", "b").map(x => x -> x.toUpperCase)(collection.breakOut)

// `y` is now `Map(a -> A, b -> B)`

Note that the types required for breakOut are inferred by the compiler from the context. If you are not assigning it to an explicitly typed local variable or passing it to a method that uniquely determines the expected type, you can always use an explicit type ascription

(Set("a", "b").map(x => x -> x.toUpperCase)(breakOut): Map[String, String])

to obtain an expression of the right type.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
  • 1
    @GuillermoGutiérrez I'd rather treat the lengthy list of type parameters of `breakOut` as an implementation detail, and ascribe the type from the outside whenever possible, otherwise the type parameter list looks way too noisy and scary, and with too many redundant details ;] – Andrey Tyukin Mar 05 '19 at 14:47
  • 1
    Agree @Andrey Tyukin, its more clear and a lot less scary that way. – Guillermo Gutiérrez Mar 05 '19 at 14:58
2

You can use foldLeft instead of fold:

val x: Set[String] = Set("asds", "reqrq", "dadas")
x.foldLeft(Map.empty[String, String]) { (p, q) =>
    p + (q -> doSomething(q))
}

Have a look at Scala: fold vs foldLeft for the more detail.

Feyyaz
  • 3,147
  • 4
  • 35
  • 50