41

What's the best way to convert a List of Lists in scala (2.9)?

I have a list:

List[List[A]]

which I want to convert into

List[A]

How can that be achieved recursively? Or is there any other better way?

Valy Dia
  • 2,781
  • 2
  • 12
  • 32
A Far
  • 425
  • 1
  • 4
  • 6

6 Answers6

59

List has the flatten method. Why not use it?

List(List(1,2), List(3,4)).flatten
> List(1,2,3,4)
Jan
  • 1,767
  • 16
  • 18
  • 2
    How will you flatten this `List(1, List(2,3), 4, List(5,6,7))` Expected result is `List(1, 2, 3, 4, 5,6,7)` – andres.santana Dec 28 '14 at 19:08
  • 3
    the above list is heterogeneous, flatten wont work there. You can do something like: List(1, List(2,3), 4, List(5,6,7)).collect{case i:Int => List(i); case l @ a :: b => l}.flatten – Jan Mar 14 '15 at 01:16
13

.flatten is obviously the easiest way, but for completeness you should also know about flatMap

 val l = List(List(1, 2), List(3, 4))
 println(l.flatMap(identity))

and the for-comprehension equivalent

 println(for (list <- l; x <- list) yield x)

flatten is obviously a special case of flatMap, which can do so much more.

Dave Griffith
  • 20,435
  • 3
  • 55
  • 76
10

Given the above example, I'm not sure you need recursion. Looks like you want List.flatten instead.

e.g.

scala> List(1,2,3)
res0: List[Int] = List(1, 2, 3)

scala> List(4,5,6)
res1: List[Int] = List(4, 5, 6)

scala> List(res0,res1)
res2: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6)) 

scala> res2.flatten
res3: List[Int] = List(1, 2, 3, 4, 5, 6)
Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
7

If your structure can be further nested, like:

List(List(1, 2, 3, 4, List(5, 6, List(7, 8))))

This function should give you the desire result:

def f[U](l: List[U]): List[U] = l match {
  case Nil => Nil
  case (x: List[U]) :: tail => f(x) ::: f(tail)
  case x :: tail => x :: f(tail)
}
Maroun
  • 94,125
  • 30
  • 188
  • 241
0

You don't need recursion but you can use it if you want:

def flatten[A](list: List[List[A]]):List[A] = 
  if (list.length==0) List[A]() 
  else list.head ++ flatten(list.tail)

This works like flatten method build into List. Example:

scala> flatten(List(List(1,2), List(3,4)))
res0: List[Int] = List(1, 2, 3, 4)
Paweł Janik
  • 121
  • 1
  • 6
0

If you want to use flatmap, here is the the way

Suppose that you have a List of List[Int] named ll, and you want to flat it to List, many people already gives you the answers, such as flatten, that's the easy way. I assume that you are asking for using flatmap method. If it is the case, here is the way

ll.flatMap(_.map(o=>o))
buqing
  • 925
  • 8
  • 25
  • How is this answer different from the answer given by Dave Griffith 5 years ago? (Other than the fact that the older answer is cleaner and more concise.) – jwvh Mar 05 '18 at 22:35
  • You are right, almost the same. I believe that mine is easier to understand or give you some hit for the underline. I am passing a identity function instead of identity keyword. Hope that it makes sense for you – buqing Mar 06 '18 at 02:32
  • Will `ll.flatMap(_)` also do the same thing as `ll.flatMap(_.map(o=>o))` ? – akki Jan 18 '19 at 07:30
  • @akki, why don't you try it yourself? It's a moment’s work :). I bet it won't work. Since "underscore" in function literal doesn't describe "identity" function, it means an argument of that function that should be used to describe some logic. But `_ => _` will not work either. – srzhio Oct 15 '19 at 20:07