Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonic random list of booleans of length n with exactly k Trues

Say we want a list of n 0/1 elements with exactly k instances of 1. Is there a one line comprehension or a more pythonic way to do this than the following?

def random_include(n, k):
    ret = []
    to_include = set(random.sample([i for i in range(n)], k))
    for i in range(n): 
        if i in to_include:
            ret.append(1)
        ret.append(0)
like image 304
rookie Avatar asked Apr 16 '14 06:04

rookie


People also ask

How do you generate a random boolean in Python?

Use random. getrandbits() to get a random boolean value Call random. getrandbits(k) with k set to 1 to get a single random bit. A bit is either 0 (representing False ) or 1 (representing True ). Use bool() to convert the random bit into a bool.

Is 0 == False in Python?

Python assigns boolean values to values of other types. For numerical types like integers and floating-points, zero values are false and non-zero values are true.

Is true 0 in Python?

In Python True and False are equivalent to 1 and 0. Use the int() method on a boolean to get its int values. int() turns the boolean into 1 or 0. Note: that any value not equal to 'true' will result in 0 being returned.


2 Answers

Here's a one-line solution.

output = sorted([1] * k + [0] * (n - k), key=lambda k: random.random())
like image 122
merlin2011 Avatar answered Sep 28 '22 09:09

merlin2011


Use random.shuffle (documentation):

random_list = [False] * j + [True] * k
random.shuffle(random_list)

Will give you a random list with j times False and k times True.

Note that implementing a custom shuffle algorithm is often problematic, as it's very easy to write an algorithm that produces seemingly-random results, but does not offer a constant probability distribution. I.e. some sequences are more likely than others!

This was extensively explored in Jeff Atwood's blog post on the subject. The correct solution, if you want a properly shuffled sequence is to use the Fisher-Yates algorithm, which is exactly what random.shuffle() takes care to do:

def shuffle(self, x, random=None, int=int):
    randbelow = self._randbelow
    for i in reversed(range(1, len(x))):
        # pick an element in x[:i+1] with which to exchange x[i]
        j = randbelow(i+1) if random is None else int(random() * (i+1))
        x[i], x[j] = x[j], x[i]

Thus, it is best to rely on random.shuffle() and not come up with a clever way to do shuffling yourself!

like image 40
Christian Aichinger Avatar answered Sep 28 '22 08:09

Christian Aichinger