25

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.

martineau
  • 119,623
  • 25
  • 170
  • 301
Darren J. Fitzpatrick
  • 7,159
  • 14
  • 45
  • 49
  • partition is also method of strings so maybe you should reconsider naming. Also I would use the floatless second answer by Mark Dickinson. – Tony Veijalainen Jul 28 '10 at 15:09

6 Answers6

44

Call random.shuffle() on the list before partitioning it.

bobince
  • 528,062
  • 107
  • 651
  • 834
27

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

ErichBSchulz
  • 15,047
  • 5
  • 57
  • 61
3

shuffle input list.

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
2

First you randomize the list and then you split it in n nearly equal parts.

Teodor Pripoae
  • 1,388
  • 1
  • 11
  • 26
1

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
Timmmm
  • 88,195
  • 71
  • 364
  • 509
0

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']
# ]
Barney Szabolcs
  • 11,846
  • 12
  • 66
  • 91