Python has my_sample = random.sample(range(100), 10)
to randomly sample without replacement from [0, 100)
.
Suppose I have sampled n
Here's a way that doesn't build the difference set explicitly. But it does use a form of @Veedrac's "accept/reject" logic. If you're not willing to mutate the base sequence as you go along, I'm afraid that's unavoidable:
def sample(n, base, forbidden):
# base is iterable, forbidden is a set.
# Every element of forbidden must be in base.
# forbidden is updated.
from random import random
nusable = len(base) - len(forbidden)
assert nusable >= n
result = []
if n == 0:
return result
for elt in base:
if elt in forbidden:
continue
if nusable * random() < n:
result.append(elt)
forbidden.add(elt)
n -= 1
if n == 0:
return result
nusable -= 1
assert False, "oops!"
Here's a little driver:
base = list(range(100))
forbidden = set()
for i in range(10):
print sample(10, base, forbidden)