Python 将列表拆分为 n 个块
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24483182/
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
Python split list into n chunks
提问by user110
I know this question has been covered many times but my requirement is different.
我知道这个问题已被多次提及,但我的要求是不同的。
I have a list like: range(1, 26)
. I want to divide this list into a fixed number n
. Assuming n = 6.
我有这样一个列表:range(1, 26)
。我想把这个列表分成一个固定的数字n
。假设 n = 6。
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
>>> l = [ x [i:i + 6] for i in range(0, len(x), 6) ]
>>> l
[[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18], [19, 20, 21, 22, 23, 24], [25]]
As you can see I didn't get 6 chunks (six sublists with elements of original list). How do I divide a list in such a way that I get exactly n
chunks which may be even or uneven
正如你所看到的,我没有得到 6 个块(六个带有原始列表元素的子列表)。我如何以这样的方式划分列表,以便我得到n
可能是均匀或不均匀的块
回答by Sukrit Kalra
One way would be to make the last list uneven and the rest even. This can be done as follows:
一种方法是使最后一个列表不均匀,其余列表均匀。这可以按如下方式完成:
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
>>> m = len(x) // 6
>>> test = [x[i:i+m] for i in range(0, len(x), m)]
>>> test[-2:] = [test[-2] + test[-1]]
>>> test
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24, 25]]
回答by sundar nataraj
x=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
chunk = len(x)/6
l=[]
i=0
while i<len(x):
if len(l)<=4:
l.append(x [i:i + chunk])
else:
l.append(x [i:])
break
i+=chunk
print l
#output=[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24, 25]]
回答by user2963623
Assuming you want to divide into n chunks:
假设你想分成n个块:
n = 6
num = float(len(x))/n
l = [ x [i:i + int(num)] for i in range(0, (n-1)*int(num), int(num))]
l.append(x[(n-1)*int(num):])
This method simply divides the length of the list by the number of chunks and, in case the length is not a multiple of the number, adds the extra elements in the last list.
此方法简单地将列表的长度除以块的数量,如果长度不是数字的倍数,则在最后一个列表中添加额外的元素。
回答by user2963623
Try this:
尝试这个:
from __future__ import division
import math
def chunked(iterable, n):
""" Split iterable into ``n`` iterables of similar size
Examples::
>>> l = [1, 2, 3, 4]
>>> list(chunked(l, 4))
[[1], [2], [3], [4]]
>>> l = [1, 2, 3]
>>> list(chunked(l, 4))
[[1], [2], [3], []]
>>> l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> list(chunked(l, 4))
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
"""
chunksize = int(math.ceil(len(iterable) / n))
return (iterable[i * chunksize:i * chunksize + chunksize]
for i in range(n))
It returns an iterator instead of a list for efficiency (I'm assuming you want to loop over the chunks), but you can replace that with a list comprehension if you want. When the number of items is not divisible by number of chunks, the last chunk is smaller than the others.
它返回一个迭代器而不是一个列表以提高效率(我假设您想遍历块),但如果您愿意,您可以将其替换为列表理解。当项目数不能被块数整除时,最后一个块小于其他块。
EDIT: Fixed second example to show that it doesn't handle one edge case
编辑:修复了第二个示例以表明它不处理一个边缘情况
回答by Jason Mitchell
Use numpy
使用 numpy
>>> import numpy
>>> x = range(25)
>>> l = numpy.array_split(numpy.array(x),6)
or
或者
>>> import numpy
>>> x = numpy.arange(25)
>>> l = numpy.array_split(x,6);
You can also use numpy.split but that one throws in error if the length is not exactly divisible.
您也可以使用 numpy.split 但如果长度不能完全整除,则会出错。
回答by David Barragán Merino
If order doesn't matter:
如果顺序无关紧要:
def chunker_list(seq, size):
return (seq[i::size] for i in range(size))
print(list(chunker_list([1, 2, 3, 4, 5], 2)))
>>> [[1, 3, 5], [2, 4]]
print(list(chunker_list([1, 2, 3, 4, 5], 3)))
>>> [[1, 4], [2, 5], [3]]
print(list(chunker_list([1, 2, 3, 4, 5], 4)))
>>> [[1, 5], [2], [3], [4]]
print(list(chunker_list([1, 2, 3, 4, 5], 5)))
>>> [[1], [2], [3], [4], [5]]
print(list(chunker_list([1, 2, 3, 4, 5], 6)))
>>> [[1], [2], [3], [4], [5], []]
回答by pylang
more_itertools.divide
is one approach to solve this problem:
more_itertools.divide
是解决这个问题的一种方法:
import more_itertools as mit
iterable = range(1, 26)
[list(c) for c in mit.divide(6, iterable)]
Output
输出
[[ 1, 2, 3, 4, 5], # remaining item
[ 6, 7, 8, 9],
[10, 11, 12, 13],
[14, 15, 16, 17],
[18, 19, 20, 21],
[22, 23, 24, 25]]
As shown, if the iterable is not evenly divisible, the remaining items are distributed from the first to the last chunk.
如图所示,如果 iterable 不能被均匀整除,则剩余的项目从第一个块到最后一个块分布。
See more about the more_itertools
library here.
在此处查看有关该more_itertools
库的更多信息。
回答by marko.ristin
If you want to have the chunks as evenly sized as possible:
如果您想让块的大小尽可能均匀:
def chunk_ranges(items: int, chunks: int) -> List[Tuple[int, int]]:
"""
Splits the items into chunks defined by begining (inclusive) and end (exclusive) indices.
If there are fewer items than chunks, each chunk contains an item and there are fewer returned chunk indices
than the argument `chunks`.
:param items: number of items in the batch.
:param chunks: number of chunks
:return: list of (chunk begin inclusive, chunk end exclusive)
"""
assert chunks > 0, "Unexpected non-positive chunk count: {}".format(chunks)
result = [] # type: List[Tuple[int, int]]
if items <= chunks:
for i in range(0, items):
result.append((i, i + 1))
return result
chunk_size, extras = divmod(items, chunks)
start = 0
for i in range(0, chunks):
if i < extras:
end = start + chunk_size + 1
else:
end = start + chunk_size
result.append((start, end))
start = end
return result
Test case:
测试用例:
def test_chunk_ranges(self):
self.assertListEqual(chunk_ranges(items=8, chunks=1),
[(0, 8)])
self.assertListEqual(chunk_ranges(items=8, chunks=2),
[(0, 4), (4, 8)])
self.assertListEqual(chunk_ranges(items=8, chunks=3),
[(0, 3), (3, 6), (6, 8)])
self.assertListEqual(chunk_ranges(items=8, chunks=5),
[(0, 2), (2, 4), (4, 6), (6, 7), (7, 8)])
self.assertListEqual(chunk_ranges(items=8, chunks=6),
[(0, 2), (2, 4), (4, 5), (5, 6), (6, 7), (7, 8)])
self.assertListEqual(chunk_ranges(items=8, chunks=7),
[(0, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8)])
self.assertListEqual(chunk_ranges(items=8, chunks=9),
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8)])
回答by Mitendra
Hint:
暗示:
- x is the string to be split.
k is number of chunks
n = len(x)/k [x[i:i+n] for i in range(0, len(x), n)]
- x 是要拆分的字符串。
k 是块的数量
n = len(x)/k [x[i:i+n] for i in range(0, len(x), n)]
回答by Brohm
For people looking for an answer in python 3(.6) without imports.
x is the list to be split.
n is the length of chunks.
L is the new list.
对于在没有导入的情况下在 python 3(.6) 中寻找答案的人。
x 是要拆分的列表。
n 是块的长度。
L 是新列表。
n = 6
L = [x[i:i + int(n)] for i in range(0, (n - 1) * int(n), int(n))]
#[[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18], [19, 20, 21, 22, 23, 24], [25]]