2

For example, at beginning I want generate a random integer from (0,9),

at first time, the program generate 2, then I put 2 in the 'excluding' list,

next time, I need generate a number ranging between 0 to 9, and excluding 2. let's say it the second turn, the program generate 5.

The third turn, I need generate a number ranging from 0 to 9 and excluding 2 and 5.

As the range is very huge (million level), is there any method is efficient?

4
  • How is 0-9 "million level"? Commented Apr 17, 2014 at 16:21
  • Just create a list of numbers between 0 and 9 and then shuffle it, then iterate through it. Commented Apr 17, 2014 at 16:21
  • Why do you need a million? Sounds like a requirement that should be laterally traversed to me... Commented Apr 17, 2014 at 16:22
  • @jonrsharpe 0-9 is am example. Thanks Commented Apr 17, 2014 at 16:37

3 Answers 3

6

Generate the possible values once, shuffle that and pop values from that list each time:

values = range(10)
random.shuffle(values)

def get_value():
    return values.pop()

This will eventually produce all values in the range, in random order, without repetition.

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

Comments

4

As per the documentation for random.sample:

To choose a sample from a range of integers, use an xrange() object as an argument. This is especially fast and space efficient for sampling from a large population: sample(xrange(10000000), 60).

This will sample without replacement, so random.sample(xrange(n), k) gives k different numbers in the range [0, n) (for k <= n).

Comments

0

You could use function which maps integer range into same integer range with exceptions, like this:

import random

def excection(val, exceptions):
    ''' Maps range of values into
        similar range of values with exceptions missing.
        Exceptions must be sorted increasingly.

        for excample with exceptions=(2, 5) it will map
        This:       0, 1, 2, 3, 4, 5, 6
        To this:    0, 1, 3, 4, 6, 7, 8
    '''
    if not exceptions:
        return val

    for e in exceptions:
        if val < e: 
            return val # value before any exclusion is unchanged
        val += 1 # after some exclusion value is larger by one

    return val


def randint_with_exceptions(min, max, exceptions):
    r = random.randint(min, max - len(exceptions)) # generate random number in range smaller then desired by number of exceptions
    return excection(r, exceptions) # and map it to desired, more sparse sequence

for i in range(20): # test possible randoms
    print randint_with_exceptions(0, 7, (2, 5)),

from functools import partial
ex_25 = partial(excection, exceptions=(2, 5))
assert ( # unittest sequence transformation
    map(ex_25, range(5))
    == [0, 1, 3, 4, 6]
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.