假设我有一个任意长度的列表,L:
L = list(range(1000))
将该列表拆分为n
组的最佳方法是什么?这是我能够提出的最好的结构,由于某种原因,它不觉得这是完成任务的最佳方式:
n = 25
for i in range(0, len(L), n):
chunk = L[i:i+25]
是否有内置功能可以解决这个问题?
编辑:早期的答案正在将我的for循环重新编入listcomp,这不是主意;你基本上以不同的形式给我我的确切答案。我看到是否有其他方法可以实现这一点,就像列表上的假设.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]
答案 0 :(得分:110)
你走了:
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
慢答案 1 :(得分:42)
怎么样:
>>> 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]]
答案 2 :(得分:38)
A Python recipe(在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]]
答案 3 :(得分:13)
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开始才能以完整的组开头。)
答案 4 :(得分:8)
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。
答案 5 :(得分:0)
这是递归版本。这是低效的,因为Python有递归限制,但是这个版本说明了每个任务都可以通过递归来解决。
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