将一个Scala列表拆分成n个交错的列表

6

假设有一个List,例如:

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

什么是将列表拆分为 n 个子列表的最佳方法,并以循环方式将项目放入每个列表中?

例如,如果 n = 3,则结果应为:

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

我认为在集合API中应该有一种方法可以做到这一点,但我似乎找不到它。
优秀的一行代码能加分哦 ;)

使用流的类似问题:https://dev59.com/znPYa4cB1Zd3GeqPhlUe - AmigoNico
3个回答

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

5

这里是一个简单的一行代码:

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

很遗憾,当您的列表不可转置时,它将无法工作。

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

您可以使用以下方法使其可转置,然后应用上述方法。
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))

ys.grouped(3) 是一个打字错误吗? - senia
@senia,为什么会是打字错误呢? - missingfaktor
使用 round(list, 0) 会导致 OutOfMemoryError - senia
是的,我知道。这个函数并不完全可靠。 - missingfaktor
所有的答案都很棒,伙计们。每个人都得到了点赞!感谢你们向我展示如何使用转置。那就是我一直在寻找的方法。但是,在经过深思熟虑后,@senia因为最优雅的一行代码而获得了选中! - Chris B

1
如果您不关心它是否是轮询的,可以这样做:
val list = List(1, 2, 3, 4, 5, 6, 7)
list.grouped(Math.ceil(list.size / 3))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接