Reputation: 7409
I have read the answers to the Slicing a list into n nearly-equal-length partitions [duplicate] question.
This is the accepted answer:
def partition(lst, n):
division = len(lst) / float(n)
return [ lst[int(round(division * i)): int(round(division * (i + 1)))] for i in xrange(n) ]
I am wondering, how does one modify these solutions in order to randomly assign items to a partition as opposed to incremental assignment.
Upvotes: 25
Views: 49550
Reputation: 12514
The random partition that also preserves the order:
def partition_preserve_order(list_in, n):
indices = list(range(len(list_in)))
shuffle(indices)
index_partitions = [sorted(indices[i::n]) for i in range(n)]
return [[list_in[i] for i in index_partition]
for index_partition in index_partitions]
(that is we shuffle the indices then sort them within the partitions)
example:
random_partition_preserve_order(list('abcdefghijklmnopqrstuvxyz'), 3)
# [
# ['c', 'd', 'g', 'm', 'p', 'r', 'v', 'x', 'y'],
# ['b', 'e', 'h', 'k', 'o', 'q', 't', 'u'],
# ['a', 'f', 'i', 'j', 'l', 'n', 's', 'z']
# ]
Upvotes: 0
Reputation: 96586
Shuffling the list doesn't preserve order. You could do something like this instead (pretty easy to adapt to more than two parts). Completely untested.
from __future__ import annotations
from typing import TypeVar
import random
T = TypeVar("T")
def partition_list(s: list[T]) -> tuple[list[T], list[T]]:
"""
Randomly partition a list into two lists, preserving order. The number to
take is drawn from a uniform distribution.
"""
len_a = random.randint(0, len(s))
len_b = len(s) - len_a
put_in_a = [True] * len_a + [False] * len_b
random.shuffle(put_in_a)
a: list[T] = []
b: list[T] = []
for val, in_a in zip(s, put_in_a):
if in_a:
a.append(val)
else:
b.append(val)
return a, b
Upvotes: 1
Reputation: 15659
Complete 2018 solution (python 3.6):
import random
def partition (list_in, n):
random.shuffle(list_in)
return [list_in[i::n] for i in range(n)]
Beware! this may mutate your original list
Upvotes: 29
Reputation: 1394
First you randomize the list and then you split it in n nearly equal parts.
Upvotes: 2