Jesvin Jose
Jesvin Jose

Reputation: 23078

Why cant this flatMap work?

I want a nested list of (k,v) tuples transformed to a flat list of (v,k) in Scala 2.9.3. I tried putting the required function literal in a flatMap. But this happens:

scala> List( List( (1,"123"), (1,"abc")), List( (45, "qwer")) ).flatMap{ case (k,v) => (v,k) }
<console>:16: error: constructor cannot be instantiated to expected type;
 found   : (T1, T2)
 required: List[(Int, java.lang.String)]
       List( List( (1,"123"), (1,"abc")), List( (45, "qwer")) ).flatMap{ case (k,v) => (v,k) }
                                                                              ^
<console>:16: error: not found: value v
       List( List( (1,"123"), (1,"abc")), List( (45, "qwer")) ).flatMap{ case (k,v) => (v,k) }
                                                                                        ^
<console>:16: error: not found: value k
       List( List( (1,"123"), (1,"abc")), List( (45, "qwer")) ).flatMap{ case (k,v) => (v,k) }
                                                                                      ^

Why is this happening to me?

Upvotes: 1

Views: 3715

Answers (2)

senia
senia

Reputation: 38045

You should use flatten and map here, not flatMap.

flatMap on List[a] takes function A => List[B] (actually not List[B], but any collection of B) and returns List[B]. This is not your case.

You have a function C => B, not List[C] => List[B]. In your case A is List[C].

map on List[A] takes a function A => B and returns List[B].

val listOfLists = List( List( (1,"123"), (1,"abc")), List( (45, "qwer")) )
listOfLists.flatten.map{ case (k,v) => (v,k) }
// List[(String, Int)] = List((123,1), (abc,1), (qwer,45))

You could use flatMap, but for List[List[A]] you have to provide a function that takes List[A] as an argument like this:

listOfLists.flatMap( _.map{case (k,v) => (v,k)} )
// List[(String, Int)] = List((123,1), (abc,1), (qwer,45))

Upvotes: 3

R&#252;diger Klaehn
R&#252;diger Klaehn

Reputation: 12565

This will work:

scala> val m =  List( List( (1,"123"), (1,"abc")), List( (45, "qwer")) )
m: List[List[(Int, java.lang.String)]] = List(List((1,123), (1,abc)), List((45,qwer)))

scala> m.flatten.map { case (k,v) => (v,k) }
res0: List[(java.lang.String, Int)] = List((123,1), (abc,1), (qwer,45))

Basically you first flatten the nested list, then map to reorder the tuples.

Upvotes: 1

Related Questions