360

I know how to generate a random number within a range in Python.

random.randint(numLow, numHigh)

And I know I can put this in a loop to generate n amount of these numbers

for x in range (0, n):
    listOfNumbers.append(random.randint(numLow, numHigh))

However, I need to make sure each number in that list is unique. Other than a load of conditional statements, is there a straightforward way of generating n number of unique random numbers?

The important thing is that each number in the list is different to the others..

So

[12, 5, 6, 1] = good

But

[12, 5, 5, 1] = bad, because the number 5 occurs twice.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Chris Headleand
  • 6,003
  • 16
  • 51
  • 69
  • Take a look: [Create random list of integers in Python](http://stackoverflow.com/questions/4172131/create-random-list-of-integers-in-python). – alecxe Apr 03 '14 at 15:30

4 Answers4

576

If you just need sampling without replacement:

>>> import random
>>> random.sample(range(1, 100), 3)
[77, 52, 45]

random.sample takes a population and a sample size k and returns k random members of the population.

If you have to control for the case where k is larger than len(population), you need to be prepared to catch a ValueError:

>>> try:
...   random.sample(range(1, 2), 3)
... except ValueError:
...   print('Sample size exceeded population size.')
... 
Sample size exceeded population size
Two-Bit Alchemist
  • 17,966
  • 6
  • 47
  • 82
  • 36
    Using `random.sample(xrange(1, 100), 3)` - with **xrange** instead of range - speeds the code a lot, particularly if you have a big range, since it will only generate on-demand the required 3 numbers (or more if the sampling without replacement needs it), but not the whole range. For example: `%timeit random.sample(xrange(10000), 3)` = 4.92 µs per loop, `%timeit random.sample(range(10000), 3)` = 126 µs per loop – gaborous May 16 '15 at 19:51
  • 52
    If you're using Python2, yes. If you're using Python 3 as in my answer it's already doing this because xrange -> range in Py3k. – Two-Bit Alchemist May 18 '15 at 15:44
  • We, could instead of enclosing the `random.sample()` call inside the `try...except` block, check if the size of the sample (`3` above) is smaller or equal (`<=`) than the size of the population (`range(1, 2)` above). – Hakim Mar 11 '17 at 19:42
  • @h4k1m You can but in general EAFP (try/except) is stylistically preferred to LBYL (if/else) in Python. – Two-Bit Alchemist Mar 14 '17 at 17:33
  • `3` can be replaced with `randint(1, N)` – DanielBell99 Mar 15 '22 at 12:24
  • This does not apply for float number, to create a list of float sampl = np.random.uniform(low=0.5, high=13.3, size=(50,)) refer to this link https://stackoverflow.com/questions/22071987/generate-random-array-of-floats-between-a-range – Tom Tom Mar 04 '23 at 10:20
33

Generate the range of data first and then shuffle it like this

import random
data = list(range(numLow, numHigh))
random.shuffle(data)
print data

By doing this way, you will get all the numbers in the particular range but in a random order.

But you can use random.sample to get the number of elements you need, from a range of numbers like this

print random.sample(range(numLow, numHigh), 3)
Michael Currie
  • 13,721
  • 9
  • 42
  • 58
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • 8
    To shuffle a range in python 3 you first need to cast it to a list: `data = list(range(numLow, numHigh))`, otherwise you will get an error. – CheshireCat Jun 05 '19 at 08:26
16

You could add to a set until you reach n:

setOfNumbers = set()
while len(setOfNumbers) < n:
    setOfNumbers.add(random.randint(numLow, numHigh))

Be careful of having a smaller range than will fit in n. It will loop forever, unable to find new numbers to insert up to n

mhlester
  • 22,781
  • 10
  • 52
  • 75
9

You could use the random.sample function from the standard library to select k elements from a population:

import random
random.sample(range(low, high), n)

In case of a rather large range of possible numbers, you could use itertools.islice with an infinite random generator:

import itertools
import random

def random_gen(low, high):
    while True:
        yield random.randrange(low, high)

gen = random_gen(1, 100)
items = list(itertools.islice(gen, 10))  # Take first 10 random elements

After the question update it is now clear that you need n distinct (unique) numbers.

import itertools
import random

def random_gen(low, high):
    while True:
        yield random.randrange(low, high)

gen = random_gen(1, 100)

items = set()

# Try to add elem to set until set length is less than 10
for x in itertools.takewhile(lambda x: len(items) < 10, gen):
    items.add(x)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
maxbublis
  • 1,273
  • 10
  • 21