Skip to content

Instantly share code, notes, and snippets.

@cbsmith
Last active January 4, 2016 10:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbsmith/8608331 to your computer and use it in GitHub Desktop.
Save cbsmith/8608331 to your computer and use it in GitHub Desktop.
My thoughts on enhancements to make random support a broader set of iterables.
import random
import itertools
def sample(population, k):
"How random.sample should really be defined."
if callable(getattr(population, '__len__', None)) and callable(getattr(population, '__getitem__', None)):
return random.sample(population, min(k, len(population)))
p = iter(population)
sample = list(itertools.islice(p, 0, k))
for p_index, item in enumerate(p, k):
r_index = random.randint(0, p_index)
if r_index < k:
sample[r_index] = item
return sample
def choice(seq):
"How random.choice should really be defined."
if callable(getattr(seq, '__len__', None)):
if callable(getattr(seq, '__getitem__', None)):
return random.choice(seq)
return next(itertools.islice(seq, random.randrange(0, len(seq)), None))
else:
return sample(seq, 1)[0]
def subset(population, k=1):
"Really how sample & choice could & should be one function."
if (k == 1):
try:
return [choice(population)]
except (IndexError, ValueError):
return []
return sample(population, k)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment