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.

1
  • partition is also method of strings so maybe you should reconsider naming. Also I would use the floatless second answer by Mark Dickinson. Commented Jul 28, 2010 at 15:09

6 Answers 6

46

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

Sign up to request clarification or add additional context in comments.

Comments

29

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

1 Comment

"may mutate" => "will mutate", but solving that is as easy as copying the original list
3

shuffle input list.

1 Comment

That absolutely makes sense. I really should have figured this out. Alas, the 10,000 hour rule is probably true :-(
2

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

Comments

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 

Comments

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'] # ] 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.