2012-06-21 2 views
5

Учитывая List, такие какSplit список в п Scala перемежения списков

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

, что это лучший способ, чтобы разбить его на п подсписков, помещая элементы в каждый список в циклическом режиме?

например. если п = 3, то результат должен быть

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

Я думал, что будет метод в коллекции API, чтобы сделать это, но я не могу найти его.

Бонусные баллы за классными остротами;)

+0

Аналогичный вопрос, используя потоки: HTTP: // StackOverflow .com/questions/17115345/split-a-stream-in-many – AmigoNico

ответ

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

Вот простой один вкладыш:

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

К сожалению, это не будет работать, если ваш список не transposeable ,

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

Вы можете использовать следующий метод, чтобы сделать его transposeable, а затем применить изложенный выше подход.

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

Соединенный:

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)' это опечатка? – senia

+0

@senia, почему это будет опечатка? – missingfaktor

+0

это должно быть 'ys.grouped (c)' – senia

0

Если вы не заботитесь о том, чтобы его круговой вы можете сделать:

val list = List(1, 2, 3, 4, 5, 6, 7) 
list.grouped(Math.ceil(list.size/3)) 
Смежные вопросы