Can I zip more than two lists together in Scala?

Viewed 40386

Given the following Scala List:

val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3"))

How can I get:

List(("a1", "a2", "a3"), ("b1", "b2", "b3"), ("c1", "c2", "c3"))

Since zip can only be used to combine two Lists, I think you would need to iterate/reduce the main List somehow. Not surprisingly, the following doesn't work:

scala> l reduceLeft ((a, b) => a zip b)
<console>:6: error: type mismatch;
 found   : List[(String, String)]
 required: List[String]
       l reduceLeft ((a, b) => a zip b)

Any suggestions one how to do this? I think I'm missing a very simple way to do it.

Update: I'm looking for a solution that can take a List of N Lists with M elements each and create a List of M TupleNs.

Update 2: As it turns out it is better for my specific use-case to have a list of lists, rather than a list of tuples, so I am accepting pumpkin's response. It is also the simplest, as it uses a native method.

11 Answers

Scala 2.12.13 and below

If you know how long the input List is, you can join the list into a Tuple and use Tuple's .zipped method:

val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3"))

println(l match {
  case l1::l2::l3::_ => (l1,l2,l3).zipped.toList
  case _ => throw new IllegalArgumentException("List is not the right length")
}) // List((a1,a2,a3), (b1,b2,b3), (c1,c2,c3))

Scastie Example - 2.12.13

>= Scala 2.13

The above solution is deprecated - use lazyZip instead:

val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3"))

println(l match {
  case l1::l2::l3::_ => (l1 lazyZip l2 lazyZip l3).toList
  case _ => throw new IllegalArgumentException("List is not the right length")
}) // List((a1,a2,a3), (b1,b2,b3), (c1,c2,c3))

Scastie Example - 2.13.0

Related