Python将列表拆分为n个块

时间:2014-06-30 05:00:26

标签: python

我知道这个问题已被多次覆盖,但我的要求不同。

我有一个列表: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]]

正如您所看到的,我没有获得6个块(六个包含原始列表元素的子列表)。如何划分列表,使得我得到的n块可能是均匀的或不均匀的

20 个答案:

答案 0 :(得分:30)

使用numpy

>>> import numpy
>>> x = range(25)
>>> l = numpy.array_split(numpy.array(x),6)

>>> import numpy
>>> x = numpy.arange(25)
>>> l = numpy.array_split(x,6);

你也可以使用numpy.split,但是如果长度不完全可分,则会抛出错误。

答案 1 :(得分:15)

如果订单无关紧要:

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], []]

答案 2 :(得分:4)

试试这个:

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))

它返回一个迭代器而不是效率列表(我假设你想循环遍历块),但如果你愿意,你可以用列表解析来替换它。当项目数不能被块数整除时,最后一个块比其他块小。

编辑:修复了第二个示例,表明它不处理一个边缘情况

答案 3 :(得分:3)

more_itertools.divide是解决此问题的一种方法:

import more_itertools as mit


iterable = range(1, 26)
[list(c) for c in mit.divide(6, iterable)]

输出

[[ 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]]

如图所示,如果iterable不可均分,则剩余的项目从第一个块分配到最后一个块。

详细了解more_itertoolshere

答案 4 :(得分:3)

以下解决方案具有很多优点:

  • 使用生成器产生结果。
  • 无进口。
  • 列表是平衡的(如果将长度17的列表分成5个,则永远不会得到4个大小为4的列表和一个大小为1的列表)。
def chunks(l, n):
    """Yield n number of striped chunks from l."""
    for i in range(0, n):
        yield l[i::n]

上面的代码为l = range(16)n = 6产生以下输出:

[0, 6, 12]
[1, 7, 13]
[2, 8, 14]
[3, 9, 15]
[4, 10]
[5, 11]

如果您需要块是连续的而不是条带化的,请使用以下方法:

def chunks(l, n):
    """Yield n number of sequential chunks from l."""
    d, r = divmod(len(l), n)
    for i in range(n):
        si = (d+1)*(i if i < r else r) + d*(0 if i < r else i - r)
        yield l[si:si+(d+1 if i < r else d)]

l = range(16)n = 6的哪个产生:

[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9, 10, 11]
[12, 13]
[14, 15]

有关生成器优点的更多信息,请参见this stackoverflow link

答案 5 :(得分:2)

假设您要分成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):])

此方法只是将列表的长度除以块的数量,如果长度不是数字的倍数,则在最后一个列表中添加额外的元素。

答案 6 :(得分:2)

我的答案是简单地使用python内置Slice:

# Assume x is our list which we wish to slice
x = range(1, 26)
# Assume we want to slice it to 6 equal chunks
result = []
for i in range(0, len(x), 6):
    slice_item = slice(i, i + 6, 1)
    result.append(x[slice_item])

# Result would be equal to 

[[0,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]]

答案 7 :(得分:1)

我只想做 (假设你想要 n 个块)

import numpy as np

k = int(np.ceil(len(x) / n))
l = [x[i, i + k] for i in range(0, len(x), k)]

答案 8 :(得分:1)

除非我误解了这个问题,否则你可以拿出多余的东西并将其附加到最后一个列表中:

import pprint
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]

def group(lst, div):
    lst = [ lst[i:i + len(lst)/div] for i in range(0, len(lst), len(lst)/div) ] #Subdivide list.
    if len(lst) > div: # If it is an uneven list.
        lst[div-1].extend(sum(lst[div:],[])) # Take the last part of the list and append it to the last equal division.
    return lst[:div] #Return the list up to that point.

l = group(x, 6)

pprint.pprint(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]]

注意:您可以使用比sum(l, [])更快的方法来压缩列表,但为了简洁起见,我正在使用它。

答案 9 :(得分:1)

一种方法是使最后一个列表不均匀,其余列表均匀。这可以按如下方式完成:

>>> 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]]

答案 10 :(得分:1)

此解决方案基于Python 3文档中的“ grouper”邮政编码模式。小增加的是,如果N不能将列表长度平均分配,则所有多余项都将放入第一个块中。

import itertools

def segment_list(l, N):
    chunk_size, remainder = divmod(len(l), N)
    first, rest = l[:chunk_size + remainder], l[chunk_size + remainder:]
    return itertools.chain([first], zip(*[iter(rest)] * chunk_size))

用法示例:

>>> my_list = list(range(10))
>>> segment_list(my_list, 2)
[[0, 1, 2, 3, 4], (5, 6, 7, 8, 9)]
>>> segment_list(my_list, 3)
[[0, 1, 2, 3], (4, 5, 6), (7, 8, 9)]
>>>

此解决方案的优点在于,它保留了原始列表的顺序,并且以一种功能样式编写,该函数样式在调用时仅对列表进行一次惰性计算。

请注意,因为它返回迭代器,所以结果只能使用一次。如果想要方便非延迟列表,可以将结果包装在list中:

>>> x = list(segment_list(my_list, 2))
>>> x
[[0, 1, 2, 3, 4], (5, 6, 7, 8, 9)]
>>> x
[[0, 1, 2, 3, 4], (5, 6, 7, 8, 9)]
>>>

答案 11 :(得分:1)

如果您的列表包含不同类型的元素或存储不同类型值的可迭代对象(某些元素是整数,有些是字符串),则使用{{1}中的array_split函数}打包将其拆分,您将获得具有相同类型元素的块:

numpy

如果您希望在列表拆分后以块的形式获取元素的初始类型,则可以从import numpy as np data1 = [(1, 2), ('a', 'b'), (3, 4), (5, 6), ('c', 'd'), ('e', 'f')] chunks = np.array_split(data1, 3) print(chunks) # [array([['1', '2'], # ['a', 'b']], dtype='<U11'), array([['3', '4'], # ['5', '6']], dtype='<U11'), array([['c', 'd'], # ['e', 'f']], dtype='<U11')] data2 = [1, 2, 'a', 'b', 3, 4, 5, 6, 'c', 'd', 'e', 'f'] chunks = np.array_split(data2, 3) print(chunks) # [array(['1', '2', 'a', 'b'], dtype='<U11'), array(['3', '4', '5', '6'], dtype='<U11'), # array(['c', 'd', 'e', 'f'], dtype='<U11')] 包中修改array_split函数中的source code或使用this implementation

numpy

答案 12 :(得分:0)

对于在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]]

答案 13 :(得分:0)

此函数将返回列表的列表,列表中具有设置的最大值(块)。

def chuncker(list_to_split, chunk_size):
    list_of_chunks =[]
    start_chunk = 0
    end_chunk = start_chunk+chunk_size
    while end_chunk <= len(list_to_split)+chunk_size:
        chunk_ls = list_to_split[start_chunk: end_chunk]
        list_of_chunks.append(chunk_ls)
        start_chunk = start_chunk +chunk_size
        end_chunk = end_chunk+chunk_size    
    return list_of_chunks

示例:

ls = list(range(20))

chuncker(list_to_split = ls, chunk_size = 6)

输出:

[[0,1,2,3,4,5],[6,7,8,8,9,10,11],[12,13,14,15,15,16,17],[18,19 ]]

答案 14 :(得分:0)

def chunks(lst, n_chunks):
  n = (len(lst) + n_chunks - 1) // n_chunks
  for i in range(0, len(lst), n):
    yield lst[i:i+n]
>>> list(chunks([0,1,2,3,4,5,6], 3))
[[0, 1, 2], [3, 4, 5], [6]]
>>> list(chunks([0,1,2,3,4,5,6,7], 3))
[[0, 1, 2], [3, 4, 5], [6, 7]]
>>> list(chunks([0,1,2,3,4,5,6,7,8], 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]

# as for your example
>>> 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]
>>> list(chunks(x, 6))
[[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]]

参考:How do you split a list into evenly sized chunks?

答案 15 :(得分:0)

arr1=[-20, 20, -10, 0, 4, 8, 10, 6, 15, 9, 18, 35, 40, -30, -90, 99]
n=4
final = [arr1[i * n:(i + 1) * n] for i in range((len(arr1) + n - 1) // n )]
print(final)

输出:

  

[[-20,20,-10,0],[4,8,10,6],[15,9,18,35],[40,-30,-90,   99]]

答案 16 :(得分:0)

给我2美分。

from math import ceil

size = 3
seq = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

chunks = [
    seq[i * size:(i * size) + size]
    for i in range(ceil(len(seq) / size))
]

# [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11]]

答案 17 :(得分:0)

提示:

  • x是要分割的字符串。
  • k是块数

    n = len(x)/k
    
    [x[i:i+n] for i in range(0, len(x), n)]
    

答案 18 :(得分:0)

如果您希望块的大小尽可能均匀:

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

测试用例:

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)])

答案 19 :(得分:-1)

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]]