Skip to content

Instantly share code, notes, and snippets.

@danesherbs
Last active October 14, 2022 14:58
Show Gist options
  • Save danesherbs/5cc6fd74abbb66c15effc2e266e3ce8e to your computer and use it in GitHub Desktop.
Save danesherbs/5cc6fd74abbb66c15effc2e266e3ce8e to your computer and use it in GitHub Desktop.
Function to sample without replacement and optionally include or exclude items
def sample(seq: Sequence, k: int, include: Union[None, set] = None, exclude: Union[None, set] = None) -> Sequence:
"""Samples `k` items from `seq` without replacement, optionally including or excluding items."""
# pre-condition
assert k >= 0, "Number of items to sample must be non-negative"
assert k <= len(seq), f"Cannot sample {k} items without replacement from a sequence with {len(seq)} items"
if include is None:
include = set()
if exclude is None:
exclude = set()
filtered_exclude = set(item for item in exclude if item in seq)
assert len(include) <= k, "Number of items to include can't exceed number of items to sample"
assert len(seq) - len(filtered_exclude) >= k, "Not enough items to sample from sequence after excluding items"
assert len(include.intersection(exclude)) == 0, "Sets `include` and `exclude` must be mutually exclusive"
# sample
filtered_seq = [item for item in seq if item not in include.union(exclude)]
sampled = random.sample(filtered_seq, k-len(include)) + list(include)
sampled = random.sample(sampled, k)
# post-condition
assert len(sampled) == k, "Sampled items must be of length `k`"
for item in include:
assert item in sampled, "Sampled items must include all items in `include`"
for item in exclude:
assert item not in sampled, "Sampled items must not include any items in `exclude`"
return sampled
sample(["dog", "cat", "lizard"], k=2, include={"dog"}, exclude={"lizard"}) # ["dog", "cat"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment