Split scala list into n interlacing lists

Given a List , for example

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

What is the best way to split it into n sub-lists by putting items in each list with a rounded mask?

eg. if n = 3, the result should be

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

I thought the method would be used in the collection API, but I cannot find it.

Bonus points for cool single-line;)

+5
source share
3 answers
 scala> def round[T](l: List[T], n: Int) = (0 until n).map{ i => l.drop(i).sliding(1, n).flatten.toList }.toList round: [T](l: List[T], n: Int)List[List[T]] scala> round((1 to 7).toList, 3) res4: List[List[Int]] = List(List(1, 4, 7), List(2, 5), List(3, 6)) 
+10
source

Here is a simple single line layer:

 scala> List.range(1, 10) res11: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9) scala> res11.grouped(3).toList.transpose res12: List[List[Int]] = List(List(1, 4, 7), List(2, 5, 8), List(3, 6, 9)) 

Unfortunately, this will not work if your list is not migrated.

 scala> List.range(1, 8).grouped(3).toList.transpose java.lang.IllegalArgumentException: transpose requires all collections have the same size 

You can use the following method to make it transposable, and then apply the above approach.

 scala> def extend[A](xs: List[A], c: Int): List[Option[A]] = { | val n = Stream.iterate(c)(c +).find(_ >= xs.length).get | xs.map(Some(_)).padTo(n, None) | } extend: [A](xs: List[A], c: Int)List[Option[A]] scala> List.range(1, 8) res13: List[Int] = List(1, 2, 3, 4, 5, 6, 7) scala> extend(res13, 3).grouped(3).toList.transpose.map(_.flatten) res14: List[List[Int]] = List(List(1, 4, 7), List(2, 5), List(3, 6)) 

Combine together:

 scala> def round[A](xs: List[A], c: Int) = { | val n = Stream.iterate(c)(c +).find(_ >= xs.length).get | val ys = xs.map(Some(_)).padTo(n, None) | ys.grouped(c).toList.transpose.map(_.flatten) | } round: [A](xs: List[A], c: Int)List[List[A]] scala> round(List.range(1, 10), 3) res16: List[List[Int]] = List(List(1, 4, 7), List(2, 5, 8), List(3, 6, 9)) scala> round(List.range(1, 8), 3) res17: List[List[Int]] = List(List(1, 4, 7), List(2, 5), List(3, 6)) 
+4
source

If you don't care about making it round, you can do:

 val list = List(1, 2, 3, 4, 5, 6, 7) list.grouped(Math.ceil(list.size / 3)) 
0
source

All Articles