list 将列表拆分为具有固定元素数量的多个列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7459174/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Split list into multiple lists with fixed number of elements
提问by Johnny Everson
How to split a List of elements into lists with at most N items?
如何将元素列表拆分为最多包含 N 个项目的列表?
ex: Given a list with 7 elements, create groups of 4, leaving the last group possibly with less elements.
例如:给定一个包含 7 个元素的列表,创建 4 个组,最后一组可能有更少的元素。
split(List(1,2,3,4,5,6,"seven"),4)
=> List(List(1,2,3,4), List(5,6,"seven"))
回答by Kipton Barros
I think you're looking for grouped
. It returns an iterator, but you can convert the result to a list,
我想你正在寻找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))
回答by Dorjee
There is much easier way to do the task using sliding method. It works this way:
使用滑动方法有更简单的方法来完成任务。它是这样工作的:
val numbers = List(1, 2, 3, 4, 5, 6 ,7)
Lets say you want to break the list into smaller lists of size 3.
假设您想将列表分成大小为 3 的较小列表。
numbers.sliding(3, 3).toList
will give you
会给你
List(List(1, 2, 3), List(4, 5, 6), List(7))
回答by Luigi Plinge
Or if you want to make your own:
或者,如果您想自己制作:
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)
}
Use:
用:
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))
edit: upon reviewing this 2 years later, I wouldn't recommend this implementation since size
is O(n), and hence this method is O(n^2), which would explain why the built-in method becomes faster for large lists, as noted in comments below. You could implement efficiently as follows:
编辑:在 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)
or even (slightly) more efficiently using splitAt
:
甚至(稍微)更有效地使用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)
}
回答by Mike
I am adding a tail recursive version of the split method since there was some discussion of tail-recursion versus recursion. I have used the tailrec annotation to force the compiler to complain in case the implementation is not indeed tail-recusive. Tail-recursion I believe turns into a loop under the hood and thus will not cause problems even for a large list as the stack will not grow indefinitely.
我添加了 split 方法的尾递归版本,因为有一些关于尾递归与递归的讨论。我已经使用 tailrec 注释来强制编译器抱怨,以防实现确实不是尾递归。我相信尾递归会变成一个循环,因此即使对于大列表也不会导致问题,因为堆栈不会无限增长。
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)
}
回答by Hydrosan
I think this is the implementation using splitAt instead of take/drop
我认为这是使用 splitAt 而不是 take/drop 的实现
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)