GrueEmerald
GrueEmerald

Reputation: 3

Randomly partition a list into n sublists (Python)

I want to create a function function(list, n) that randomly divides a list into n sublists (not necessarily of equal size)—forming a partition. This should all be random, both with respect to the sizes of the sublists, but also the elements included. (Empty sublists are OK!)

Example 1: function([1,1,4,8,5,5], 3) could output [[5,8], [1], [1,5,4]] .

Example 2: function([77, 88, 3], 2) could output [[],[3,77,88]].

I'm very new to Python, so I don't have that many ideas. Firstly, you could perhaps shuffle the list:

import random

def shuffle_list(list):
    return random.shuffle(list)

From here I don't really know. Perhaps I want to randomly generate n - 1 distinct numbers in range(len(list)+1), and they would correspond to places where the list could be split up.

Any help would be appreciated!

Upvotes: 0

Views: 557

Answers (4)

Adon Bilivit
Adon Bilivit

Reputation: 27404

There's no need to explicitly shuffle the input list if you select the values at random. For example:

from random import choice

def shuffle_list(lst, n):
    output = [[] for _ in range(n)]
    while lst:
        lst.remove(e := choice(lst))
        choice(output).append(e)
    return output

print(shuffle_list([1,1,4,8,5,5], 4))

Upvotes: 0

potato_cannon
potato_cannon

Reputation: 432

Just pop the lst to oblivion:

import random

def shuffle_list(lst, c):
    random.shuffle(lst)

    out = [[] for _ in range(c)]

    while len(lst):
        out[random.randint(0,c-1)].append(lst.pop())
        
    return out

output:

shuffle_list([1,2,3,4,5,6,7], 3) # [[3, 1], [4, 7], [2, 5, 6]]

Upvotes: -1

trincot
trincot

Reputation: 351369

You could take a sample of the possible indices in the given list, sort them, and then create the slices with that information:

import random

def partition(lst, n):
    lst = lst[:]  # take a copy so not to mutate the input list
    random.shuffle(lst)
    indexes = sorted(random.sample(range(1, len(lst)), n - 1))
    return [
        lst[start:end]
        for start, end in zip([0] + indexes, indexes + [len(lst)])
    ]

res = partition([1,1,4,8,5,5], 3)

Upvotes: 0

True do day
True do day

Reputation: 308

You have good idea: you can use the random module to shuffle the list and then select random lengths for the partitions.

import random

def function(lst, n):
    # Shuffle the list
    random.shuffle(lst)

    # Initialize the output lists
    partitions = []

    # Generate random lengths for the partitions
    lengths = sorted(random.sample(range(0, len(lst)), n - 1))
    lengths.append(len(lst))

    # Use the lengths to slice the list and create the partitions
    start = 0
    for end in lengths:
        partitions.append(lst[start:end])
        start = end

    return partitions

print(function([1, 1, 4, 8, 5, 5], 3))  # [[4, 8], [5], [1, 1, 7, 5]]

Upvotes: 1

Related Questions