How to flatten a List of Lists in Scala with flatten

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 10.15, “How to Flatten a List of Lists in Scala with flatten

Problem

You have a list of lists (a sequence of sequences) and want to create one list (sequence) from them.

Solution

Use the flatten method to convert a list of lists into a single list. To demonstrate this, first create a list of lists:

scala> val lol = List(List(1,2), List(3,4))
lol: List[List[Int]] = List(List(1, 2), List(3, 4))

Calling the flatten method on this list of lists creates one new list:

scala> val result = lol.flatten
result: List[Int] = List(1, 2, 3, 4)

As shown, flatten does what its name implies, flattening the lists held inside the outer list into one resulting list.

Though I use the term “list” here, the flatten method isn’t limited to a List; it works with other sequences (Array, ArrayBuffer, Vector, etc.) as well:

scala> val a = Array(Array(1,2), Array(3,4))
a: Array[Array[Int]] = Array(Array(1, 2), Array(3, 4))

scala> a.flatten
res0: Array[Int] = Array(1, 2, 3, 4)

In the real world, you might use flatten to convert a list of couples attending a wedding into a single list of all people attending the wedding. Calling flatten on a List[List[String]] does the job:

scala> val couples = List(List("kim", "al"), List("julia", "terry"))
couples: List[List[String]] = List(List(kim, al), List(julia, terry))

scala> val people = couples.flatten
people: List[String] = List(kim, al, julia, terry)

If you really want to have fun, capitalize each element in the resulting list and then sort the list:

scala> val people = couples.flatten.map(_.capitalize).sorted
people: List[String] = List(Al, Julia, Kim, Terry)

This helps to demonstrate the power of the Scala collections methods. (Imagine trying to write that code with only a for loop.)

In a social-networking application, you might do the same thing with a list of friends, and their friends:

val myFriends = List("Adam", "David", "Frank")
val adamsFriends = List("Nick K", "Bill M")
val davidsFriends = List("Becca G", "Kenny D", "Bill M")
val friendsOfFriends = List(adamsFriends, davidsFriends)

Because friendsOfFriends is a list of lists, you can use flatten to accomplish many tasks with it, such as creating a unique list of the friends of your friends:

scala> val uniqueFriendsOfFriends = friendsOfFriends.flatten.distinct
uniqueFriendsOfFriends: List[String] = List(Nick K, Bill M, Becca G, Kenny D)

More on flatten in Scala

The flatten method is useful in at least two other situations. First, because a String is a sequence of Char, you can flatten a list of strings into a list of characters:

scala> val list = List("Hello", "world")
list: List[java.lang.String] = List(Hello, world)

scala> list.flatten
res0: List[Char] = List(H, e, l, l, o, w, o, r, l, d)

Second, because an Option can be thought of as a container that holds zero or one elements, flatten has a very useful effect on a sequence of Some and None elements. It pulls the values out of the Some elements to create the new list, and drops the None elements:

scala> val x = Vector(Some(1), None, Some(3), None)
x: Vector[Option[Int]] = Vector(Some(1), None, Some(3), None)

scala> x.flatten
res1: Vector[Int] = Vector(1, 3)

(You’ll also see a similar benefit when using the Scala flatMap method.)