如何将数字列表中的每个块的总和小于n?

Joh*_*tyb 3 python

我试图寻找解决方案,但我对精确术语的无知并没有帮助,希望问题的标题和下面的代码是足够的解释.

这是我到目前为止的工作:

C = [1,1,1,1,2,3,1,1,1,2,1]
sub_C = []
chunked_C = []
counter = 0
for i in C:
    counter += i
    if counter <= 3:
        sub_C.append(i)
    else:
        chunked_C.append(list(sub_C))
        del sub_C[:]
        counter = i
        sub_C.append(i)
print chunked_C
Run Code Online (Sandbox Code Playgroud)

我希望chunked_C产生:[[1,1,1],[1,2],[3],[1,1,1],[2,1]]

不知道我哪里出错了,也许有人可以提供帮助.

编辑:我纠正了错别字.

也:

稍微修改一下,我需要将列表的不完整尾部分块,即值小于3但是我的数字用完了.

例如:

C = [1,1,1,1,2,3,1,1,1,2,1,1]
so chunked_C = [[1,1,1],[1,2],[3],[1,1,1],[2,1],[1]]
Run Code Online (Sandbox Code Playgroud)

希望有道理.

进一步修订:

如果C = [1,1,1,1,1,2,3,1,1,1,2,1]

chunked_C等于[[1,1,1],[1,1],[2],[3],[1,1,1],[2,1]]

所以我猜逻辑需要进一步修改.

Gar*_*tty 6

编辑:首先,在评论中作为Ashwini指出的更正,我们需要确保我们释放最后一个块,即使它没有达到目标.

也就是说,使用itertools.groupby()以下方法可以更好地解决此问题:

import itertools

c = [1,1,1,1,2,3,1,1,1,2,1]

class group_by_sum:
    def __init__(self, target):
        self.target = 3
        self.current = False
        self.sum = 0

    def __call__(self, item):
        self.sum += item
        if self.sum > self.target:
            self.sum = item
            self.current = not self.current
        return self.current

    def group(self, iterable):
        return [tuple(items) for _, items in itertools.groupby(iterable, self)]

>>> group_by_sum(3).group(c)

[(1, 1, 1), (1, 2), (3,), (1, 1, 1), (2, 1)]
Run Code Online (Sandbox Code Playgroud)

显然,最后的便利方法不一定重要,但它使用起来更简单.


旧答案:

这可以通过生成器很好地完成:

def chunk_to_sum(iterable, target):
    chunk_sum = 0
    chunk = []
    for item in iterable:
        chunk_sum += item
        if chunk_sum > target:
            yield chunk
            chunk = [item]
            chunk_sum = item
        else:
            chunk.append(item)
    if chunk: yield chunk

>>> list(chunk_to_sum([1, 1, 1, 1, 2, 3, 1, 1, 1, 2, 1], 3))
[[1, 1, 1], [1, 2], [3], [1, 1, 1], [2, 1]]
Run Code Online (Sandbox Code Playgroud)