将列表拆分成n个组的另一种方法

假设我有一个任意长度的列表,L:

L = list(range(1000)) 

将这个列表分成n组的最好方法是什么? 这是我所能想到的最好的结构,出于某种原因,它不觉得这是完成任务的最好方式:

 n = 25 for i in range(0, len(L), n): chunk = L[i:i+25] 

有没有一个内置的这样做,我失踪了?

编辑:早期的答案是重新我的循环到一个listcomp,这不是想法; 你基本上以不同的forms给我回答我的确切答案。 我看到是否有其他方法来完成这个任务,比如列表中的假设.split 。 在昨天晚上我写的一些代码中,我也将它用作生成器:

 def split_list(L, n): assert type(L) is list, "L is not a list" for i in range(0, len(L), n): yield L[i:i+n] 

Python配方 (在Python 2.6中,使用itertools.izip_longest ):

 def grouper(n, iterable, fillvalue=None): "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" args = [iter(iterable)] * n return itertools.zip_longest(*args, fillvalue=fillvalue) 

用法示例:

 >>> list(grouper(3, range(9))) [(0, 1, 2), (3, 4, 5), (6, 7, 8)] >>> list(grouper(3, range(10))) [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)] 

如果你想让最后一个组比其他组更短,而不是填充fillvalue ,那么你可以改变代码如下:

 >>> def mygrouper(n, iterable): ... args = [iter(iterable)] * n ... return ([e for e in t if e != None] for t in itertools.zip_longest(*args)) ... >>> list(mygrouper(3, range(9))) [[0, 1, 2], [3, 4, 5], [6, 7, 8]] >>> list(mygrouper(3, range(10))) [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] 

干得好:

 list_of_groups = zip(*(iter(the_list),) * group_size) 

例:

 print zip(*(iter(range(10)),) * 3) [(0, 1, 2), (3, 4, 5), (6, 7, 8)] 

如果元素的数量不能被N整除,但是你仍然希望包含它们,你可以使用izip_longest,但是它只能在python 2.6

 izip_longest(*(iter(range(10)),) * 3) 

结果是一个生成器,所以如果你想打印它,你需要将它转换成一个列表。

最后,如果你没有python 2.6并且卡住了旧版本,但你仍然想要有相同的结果,你可以使用map:

 print map(None, *(iter(range(10)),) * 3) [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)] 

我想在目前介绍的不同方法之间加一些速度比较:

 python -m timeit -s 'from itertools import izip_longest; L = range(1000)' 'list(izip_longest(*(iter(L),) * 3))' 10000 loops, best of 3: 47.1 usec per loop python -m timeit -s 'L = range(1000)' 'zip(*(iter(L),) * 3)' 10000 loops, best of 3: 50.1 usec per loop python -m timeit -s 'L = range(1000)' 'map(None, *(iter(L),) * 3)' 10000 loops, best of 3: 50.7 usec per loop python -m timeit -s 'L = range(1000)' '[L[i:i+3] for i in range(0, len(L), 3)]' 10000 loops, best of 3: 157 usec per loop python -m timeit -s 'import itertools; L = range(1000)' '[list(group) for key, group in itertools.groupby(L, lambda k: k//3)]' 1000 loops, best of 3: 1.41 msec per loop 

列表理解和方法组明显比zip,izip_longest和map慢

怎么样:

 >>> n = 2 >>> l = [1,2,3,4,5,6,7,8,9] >>> [ l[i:i+n] for i in range(0, len(l), n) ] [[1, 2], [3, 4], [5, 6], [7, 8], [9]] 

Itertools.groupby是一个很好的工具,这里是一个简单的使用整数除法来拆分整数列表的方法:

 >>> for key, group in itertools.groupby(range(10), lambda k: k//3): ... print key, list(group) ... 0 [0, 1, 2] 1 [3, 4, 5] 2 [6, 7, 8] 3 [9] 

(该列表必须从0开始,以整个组开始。)

 n = 25 list_of_lists = [L[i:i+n] for i in range(0, len(L), n)] 

它给你的名单[[0..24], [25..49], ..]

如果len(L) % n不是0,最后一个元素( list_of_lists[-1] )的长度将是len(L)%n。

这是recursion版本。 由于Python具有recursion限制,效率很低,但是这个版本说明了每个任务都可以通过recursion来解决。

 def split_to_groups(l, n): assert (len(l) / n) < 998, "Can't split to {} groups".format(len(l) / n) if l == []: return [] else: f = [l[:n]] f.extend(split_to_groups(l[n:], n)) return f 

如果你select它们,random.sample(population,k),返回从总体序列中select的唯一元素的长度列表。 用于无需更换的随机抽样。