Search code examples
pythonlistrandomchunks

Randomly dividing a list into chunks of two or three items


I am stuck on a problem involving splitting up a list into different sized chunks. I want to have a list that is randomly split into either pairs of 2 or 3.

example:

L = [1,1,1,1,1,1,1,1,1,1,1,1]

and I want to get something out like:

L2 = [(1,1,1),(1,1),(1,1),(1,1,1),(1,1)]

but this I want to be random, so that the distribution of pairs and triplets changes everytime the code is ran.


Solution

  • As a more general approach you can use following function:

    from itertools import count
    import random
    def my_split(lst, chunks):
        def chunk_creator():
            total = 0
            while total <= len(lst):
                x = random.choice(chunks)
                yield L[total: x + total]
                total += x
            yield total - x
    
        def chunk_finder():
            for _ in count():
                chunk = list(chunk_creator())
                total = chunk.pop(-1)
                if total == len(L):
                    return chunk[:-1]
        if max(chunks) <= len(L):
            return chunk_finder()
        else:
            return None
    

    Demo :

    >>> L = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 
    >>> my_split(L, (2, 3))
    ... [[1, 1], [1, 1], [1, 1], [1, 1, 1], [1, 1, 1]]
    >>> my_split(L, (2, 3))
    ... [[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]]
    

    Explanation:

    This function is consist of to sub functions. First one is chunk_creator which it's job is creating the desire chunks based on the length of your list and return them as an iterator. Note that, the end value is the total variable which is the sum of preceding chunks.

    The second function (chunk_finder) will find the desire chunks for us by goring through an in infinity loop (itertools.count()) and checking if the value of total is equal with the length of input list.