Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mutually exclusive random sampling from a list

input = ['beleriand','mordor','hithlum','eol','morgoth','melian','thingol']

I'm having trouble creating X number of lists of size Y without repeating any elements.

What I have been doing is using:

x = 3
y = 2

import random

output = random.sample(input, y)
# ['mordor', 'thingol']

but if I repeat this then I will have repeats.

I would like the output to be something like

[['mordor', 'thingol'], ['melian', 'hithlum'], ['beleriand', 'eol']]

since I chose x = 3 (3 lists) of size y = 2 (2 elements per list).

def random_generator(x,y):
    ....
like image 539
O.rka Avatar asked Mar 31 '26 03:03

O.rka


1 Answers

You can simply shuffle the original list and then generate n groups of m elements successively from it. There may be fewer or more than that number of groups possible. Note thatinputis the name of a Python built-in function, so I renamed itwords.

import itertools
from pprint import pprint
import random

def random_generator(seq, n, m):
    rand_seq = seq[:]  # make a copy to avoid changing input argument
    random.shuffle(rand_seq)
    lists = []
    limit = n-1
    for i,group in enumerate(itertools.izip(*([iter(rand_seq)]*m))):
        lists.append(group)
        if i == limit: break  # have enough
    return lists

words = ['beleriand', 'mordor', 'hithlum', 'eol', 'morgoth', 'melian', 'thingol']
pprint(random_generator(words, 3, 2))

Output:

[('mordor', 'hithlum'), ('thingol', 'melian'), ('morgoth', 'beleriand')]

It would be more Pythonic to generate the groups iteratively. The above function could easily be turned into generator by making ityieldeach group, one-by-one, instead of returning them all in a relatively much longer list-of-lists:

def random_generator_iterator(seq, n, m):
    rand_seq = seq[:]
    random.shuffle(rand_seq)
    limit = n-1
    for i,group in enumerate(itertools.izip(*([iter(rand_seq)]*m))):
        yield group
        if i == limit: break

pprint([group for group in random_generator_iterator(words, 3, 2)])
like image 193
martineau Avatar answered Apr 02 '26 04:04

martineau