2012-06-21 10 views
5

Bei einem List wieSplit eine scala Liste in n Verschachtelung Listen

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

was ist der beste Weg, um es in n Teillisten aufgeteilt, Elemente in jede Liste in einer Round-Robin-Weise setzen?

z.B. wenn n = 3, soll das Ergebnis

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

sein dachte ich, es wäre ein Verfahren, in der Sammlung API sein, dies zu tun, aber ich kann nicht scheinen, um es zu finden.

Bonuspunkte für noble Einzeiler;)

+0

eine ähnliche Frage, mit Streams: http: // Stackoverflow .com/questions/17115345/split-a-stream-in-many – AmigoNico

Antwort

10
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)) 
4

Hier ist ein einfacher Einzeiler:

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)) 

Leider wird nicht funktionieren, es, wenn Ihre Liste nicht transposeable ist .

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

können Sie die folgende Methode verwenden, um es transposeable zu machen, und dann den oben beschriebenen Ansatz anwenden.

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)) 

zusammen:

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)) 
+0

'ys.grouped (3)' ist das ein Tippfehler? – senia

+0

@senia, warum wäre das ein Tippfehler? – missingfaktor

+0

sollte es 'ys.grouped (c)' – senia

0

Wenn Sie Sie tun können, ist es egal, es Round-Robin zu machen:

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