1
for i in generate_chunks([1, 2, 3, 4, 5], 2):
    print(i)

# [[1], [2, 3, 4, 5]]
# [[1, 2], [3, 4, 5]]
# [[1, 2, 3], [4, 5]]
# [[1, 2, 3, 4], [5]]


for i in generate_chunks([1, 2, 3, 4, 5], 3):
    print(i)

# [[1], [2], [3, 4, 5]]
# [[1, 2], [3], [4, 5]]
# [[1, 2, 3], [4], [5]]
# [[1, 2], [3, 4], [5]]
# ...

How can I implement generate_chunks(list, n)?

Essentially what generate_chunks does is splitting list in n chunks and yield a list of these chunks.

For clarification, n refers to the number of chunks, not the length of the chunks.

The order in which those lists of chunks are yielded is irrelevant, however the order of the elements in the initial list is important, so that for a given list [1, 2, 3] the result [[1], [2, 3]] would be valid whereas [[1], [3, 2] would be invalid.

(Preferably without using a 3rd-party library)

Scriptim
  • 1,743
  • 2
  • 20
  • 37
  • Have you tried using `range` and adding the chunk size to each step as the end of the slice? like `for i in range(0, len(l), s)` and then `yield l[i, i+s]` – arielnmz Oct 02 '17 at 15:40
  • @arielnmz Assuming you mean `yield l[i : i+s]`. This returns `[1, 2] [3, 4] [5]` with `s = 2` – Scriptim Oct 02 '17 at 15:46
  • What should be the output of `generate_chunks(l,4)`? – arielnmz Oct 02 '17 at 15:50
  • Each 'yield' should return a list of length 4 – Scriptim Oct 02 '17 at 15:51
  • By your previous examples, with a chunk size of 3, `[[1], [2], [3, 4, 5]]` do not appear to be chunks of length 3. – arielnmz Oct 02 '17 at 15:54
  • @arielnmz no, the OP does not really mean `chunk` size, they mean *number* of chunks – Joe Iddon Oct 02 '17 at 15:57
  • You are talking about chunks, but "all possible" sounds more like combinations. Either way, include itertools (which is not third party) in your search. – Kenny Ostrom Oct 02 '17 at 15:59
  • @PatrickHaugh, that question includes permutations, the OP seems to just want them in the same order – Joe Iddon Oct 02 '17 at 16:00
  • @JoeIddon This is so confusing: *what generate_chunks does is splitting list in n chunks* -- *Each 'yield' should return a list of length 4*. What exactly is the rule for generating such chunks? – arielnmz Oct 02 '17 at 16:01
  • @arielnmz I agree! The question is unclear – Joe Iddon Oct 02 '17 at 16:02
  • I disagree with closing this as a duplicate. The other question is asking for *all* partitions into a given number of pieces. This is asking for just some of the partitions, those in which each piece consists of contiguous elements. Thus, I am voting to reopen. – John Coleman Oct 02 '17 at 16:13
  • @JohnColeman: I agree with you. Your answer shows that we have understood the question in the same way. This is not a duplicate. – Serge Ballesta Oct 02 '17 at 16:24
  • @John (and @Serge): I think you're mistaken about it not being a duplicate. The `sorted_k_partitions()` function near the beginning of the [accepted answer](https://stackoverflow.com/a/39199937/355230) generates the grouping desired by this question—try it yourself and see. It does unnecessarily sort the final result it returns, which isn't necessary here, but that does little harm. – martineau Oct 02 '17 at 16:28
  • 2
    @martineau I also think it's not a duplicate. Briefly, that question accepts [(2,), (4,), (1, 3)] as a partition, but this one does not because 1 and 3 are not contiguous. – Matt Gregory Oct 02 '17 at 16:34

1 Answers1

7

Here is an itertools based approach:

import itertools

def chunks(items, cutpoints):
    return [items[i:j] for i,j in zip([0] + cutpoints, cutpoints + [len(items)])]

def generate_chunks(items, n):
    indices = range(1,len(items))
    for cutpoints in itertools.combinations(indices,n-1):
        yield chunks(items,list(cutpoints))

For example:

>>> for c in generate_chunks([1,2,3,4,5],4): print(c)

[[1], [2], [3], [4, 5]]
[[1], [2], [3, 4], [5]]
[[1], [2, 3], [4], [5]]
[[1, 2], [3], [4], [5]]
Joe Iddon
  • 20,101
  • 7
  • 33
  • 54
John Coleman
  • 51,337
  • 7
  • 54
  • 119
  • @SergeBallesta No you shouldn't if you read the question, the function takes the number of chunks to return so your example does not fit the input of `4` chunks – Joe Iddon Oct 02 '17 at 16:09