1

My requirement is to create a set of random numbers. I know the set size and the random number range. Therefore:

import random
def makeset(lo, hi, ss):
  s = set()
  while len(s) < ss:
    s.add(random.randint(lo, hi))
  return s

I realise that certain combinations of lo, hi & ss could result in an impossible task but that's not in scope here.

I've started learning about numpy and wondered if that module offered something that could do this in a single step - i.e., no explicit loop.

But I can't find anything in the documentation. Maybe it's not there.

Any thoughts?

DarkKnight
  • 19,739
  • 3
  • 6
  • 22
  • 4
    Do you have to do this with numpy? The same result can be achieved using `random.sample` see https://docs.python.org/3/library/random.html#random.sample – ChrisOram Jan 21 '22 at 09:23
  • https://numpy.org/doc/stable/reference/random/generated/numpy.random.rand.html – D Malan Jan 21 '22 at 09:24
  • 1
    I do not need to use numpy. I was just wondering if there was something in that module. Having said that, random.sample is what I should have used in the first place. Thank you @ChrisOram – DarkKnight Jan 21 '22 at 09:25
  • While not specifically about numpy, [this](https://stackoverflow.com/questions/9755538/how-do-i-create-a-list-of-random-numbers-without-duplicates) and [this](https://stackoverflow.com/questions/22842289/generate-n-unique-random-numbers-within-a-range) are highly related and do have a few answers with numpy. Not sure if counts as a duplicate – Tomerikoo Jan 21 '22 at 11:42

2 Answers2

2

You could use np.random.choice without replacement as follows:

import numpy as np
gen = np.random.Generator(np.random.PCG64())
def with_numpy_gen(lo, hi, ss):
  return gen.choice(np.arange(lo, hi + 1), ss, replace=False)
hilberts_drinking_problem
  • 11,322
  • 3
  • 22
  • 51
  • `numpy.random.choice` is extremely inefficient - it builds an entire permutation of the input array and then slices it to take the sample. They can't change it due to backward compatibility guarantees. – user2357112 Jan 21 '22 at 09:31
  • 1
    `numpy.random.Generator.choice` doesn't have the efficiency issue, but the old API still comes up first in all the search results, and the new API has the awkward requirement of forcing you to manage an explicit RNG object - using an explicit RNG is good practice, but it's hard to get anyone to care enough to do it. – user2357112 Jan 21 '22 at 09:34
  • @user2357112supportsMonica nevermind, I think my benchmarks were off. It still seems like using a generator is the way to go. – hilberts_drinking_problem Jan 21 '22 at 09:47
0

We could use np.random.default_rng

Construct a new Generator with the default BitGenerator (PCG64)

import numpy as np
gen = np.random.default_rng()
def makeset(lo, hi, ss):
  return set(gen.choice(np.arange(lo, hi + 1), ss, replace=False))
ansev
  • 30,322
  • 5
  • 17
  • 31