1

First of all, I'd like to say that I thought the exact same question had been answered before, but after a brief research I couldn't find any threads leading me to the answer that i wanted in here which means i didn't dig enough or missed some keywords. Sorry for that if that question is out there.

Anyways, I've started to learn python and was going through some exercises. I needed to create a list which has 10 randomly generated integers in it and each integer must have a different value.

So I've tried to compare the first element of the list with the next one and if they're the same, I tried to generate a new number with the if statement.

import random

listA = []

for i in range(0,10):
    x=random.randint(1,100)

    if listA[i] == listA[i-1]:
        x=random.randint(1,100)
    else:
        listA.append(x)

listA.sort()
print(listA)

But I've got an error saying; "list index is out of range"

I expected the if statement to start with the "0" index and count till the 9th index of the "listA" and as it goes, compare them, if the same, generate another random number. But obviously, my indexation was wrong.

Also, any other comments on the code would be appreciated.

Thanks for your time in advance.

4
  • 3
    You are doing this if listA[i] == listA[i-1] when the list is empty Commented Feb 5, 2019 at 13:16
  • 1
    Try using if x in listA: and you can use random.sample(range(1, 100), 10) for making unique list Commented Feb 5, 2019 at 13:19
  • 1
    You want to check the previous element except for the first iteration, so if i>0 and listA[i] == listA[i-1] will solve your problem. Commented Feb 5, 2019 at 13:27
  • Thank you. That was helpful. Like i said, since i'm really new to the python syntax and i'm learning with exercises, i didn't really know that was possible. Also, random.sample is totally new to me. Commented Feb 5, 2019 at 13:32

3 Answers 3

4

In Python, a set can only contain unique values, so in the following code, duplicate random numbers won't increase the length of the set:

import random

s = set()
while len(s) < 10:
    s.add(random.randint(1,100))

print(sorted(s))

Output:

[18, 20, 26, 48, 51, 72, 75, 92, 94, 99]
Sign up to request clarification or add additional context in comments.

Comments

3

Try the following.

import random

listA = []

while(len(listA) < 10):
    x = random.randint(1,100)
    if x not in listA:
        listA.append(x)

listA.sort()
print(listA)

Explanation:

You should use a while loop so that you keep generating numbers until your desired list is actually 10 numbers. When using the for loop, if you happen to generate [2, 2, 30, 40, 2, 10, 20, 83, 92, 29] at random, your list will only be 8 numbers long because the duplicate 2's will not be added, although you have already looped through your for loop 10 times.

While is the key here as you will never be able to fool proof predict how many times it will take to randomly have 10 different numbers, therefore you want to keep going while you haven't reached the desired length.

Also, the keyword in is a simple way to check if something already exists inside something else.

8 Comments

Good answer. I'd also recommend random.sample as a better alternative to the while loop.
Thank you, that worked and your explanation was understandable.
@jpp why not provide a separate answer which uses random.sample?
@Risadinha, Because that's technically another question: How do I create a list of random numbers without duplicates?. It's generally good when answering to indicate obvious and efficient alternatives, even if it goes technically beyond the original question.
@Risadinha, The core problem, in my opinion, is the OP's logic is technically incorrect. The other issue, how you can get the same result more efficiently, is also a valid concern, but doesn't explain OP's misunderstanding.
|
3

This can be thought of as sampling without replacement. In this case, you are "sampling" 10 items at random from range(1, 101) and each item that is sampled can only be sampled once (i.e. it is not "replaced" - imagine drawing numbered balls at random from a bag to understand the concept).

Sampling without replacement can be handled in one line:

import random
listA = random.sample(range(1, 101), 10)

Another way of thinking about it is to shuffle list(range(1, 101)) and take the first 10 elements:

import random
listA = list(range(1, 101))
random.shuffle(listA)
listA[:10]

Timing the different approaches

Using the %timeit magic in iPython we can compare the different approaches suggested in the answers:

def random_sample():
    import random
    return sorted(random.sample(range(1, 101), 10))

def random_shuffle():
    import random
    listA = list(range(1, 101))
    random.shuffle(listA)
    return sorted(listA[:10])

def while_loop():
    import random
    listA = []
    while(len(listA) < 10):
        x = random.randint(1, 100)
        if x not in listA:
            listA.append(x)
    return sorted(listA)

def random_set():
    import random
    s = set()
    while len(s) < 10:
        s.add(random.randint(1, 100))
    return sorted(s)

%timeit for i in range(100): random_sample()
# 1.38 ms ± 17.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit for i in range(100): random_shuffle()
# 6.81 ms ± 104 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit for i in range(100): while_loop()
# 1.61 ms ± 18.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit for i in range(100): set_approach()
# 1.48 ms ± 19.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

2 Comments

NB - the equivalent of random.randint(1,100) using a range would require range(1,101)
Note that the builtin random.sample "is especially fast and space efficient for sampling from a large population" docs.python.org/3.7/library/random.html#random.sample

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.