将列表拆分成多个具有固定数量元素的列表

如何将元素列表拆分成最多N个项目的列表?

例如:给出一个包含7个元素的列表,创build4个组,最后一个组可能会包含更less的元素。

split(List(1,2,3,4,5,6,"seven"),4) => List(List(1,2,3,4), List(5,6,"seven")) 

我想你正在寻找grouped 。 它返回一个迭代器,但是你可以把结果转换成一个列表,

 scala> List(1,2,3,4,5,6,"seven").grouped(4).toList res0: List[List[Any]] = List(List(1, 2, 3, 4), List(5, 6, seven)) 

或者如果你想自己做:

 def split[A](xs: List[A], n: Int): List[List[A]] = { if (xs.size <= n) xs :: Nil else (xs take n) :: split(xs drop n, n) } 

使用:

 scala> split(List(1,2,3,4,5,6,"seven"), 4) res15: List[List[Any]] = List(List(1, 2, 3, 4), List(5, 6, seven)) 

编辑 :审查这2年后,我不会推荐这个实现,因为size是O(n),因此这个方法是O(n ^ 2),这将解释为什么内置的方法变得更快的大型列表如下面的评论所述。 你可以有效地实现,如下所示:

 def split[A](xs: List[A], n: Int): List[List[A]] = if (xs.isEmpty) Nil else (xs take n) :: split(xs drop n, n) 

甚至(稍微)更有效地使用splitAt

 def split[A](xs: List[A], n: Int): List[List[A]] = if (xs.isEmpty) Nil else { val (ys, zs) = xs.splitAt(n) ys :: split(zs, n) } 

我添加了split方法的尾recursion版本,因为有一些关于尾recursion和recursion的讨论。 我已经使用tailrec注释来强制编译器抱怨的情况下,实施不是确实尾巴recusive。 尾recursion我相信变成了引擎盖下的循环,因此即使是大型列表也不会造成问题,因为堆栈不会无限增长。

 import scala.annotation.tailrec object ListSplitter { def split[A](xs: List[A], n: Int): List[List[A]] = { @tailrec def splitInner[A](res: List[List[A]], lst: List[A], n: Int) : List[List[A]] = { if(lst.isEmpty) res else { val headList: List[A] = lst.take(n) val tailList : List[A]= lst.drop(n) splitInner(headList :: res, tailList, n) } } splitInner(Nil, xs, n).reverse } } object ListSplitterTest extends App { val res = ListSplitter.split(List(1,2,3,4,5,6,7), 2) println(res) } 

使用滑动方法可以更简单地完成任务。 它以这种方式工作:

 val numbers = List(1, 2, 3, 4, 5, 6 ,7) 

比方说,你想要将列表分成3个较小的列表。

 numbers.sliding(3, 3).toList 

会给你

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

我认为这是使用splitAt而不是采取/放下的实现

 def split [X] (n:Int, xs:List[X]) : List[List[X]] = if (xs.size <= n) xs :: Nil else (xs.splitAt(n)._1) :: split(n,xs.splitAt(n)._2)