How to prevent random function printing the same row more than once from xslx file in python

Question:

So I’m a python beginner and don’t really know the gist of random functions. The following is my code (but only partially so it may not make sense but it has the point of what I wanted to ask. I put the conclusion of my code on the beginning of the paragraph after the code though. P.S. the code works):

if (1 <= numb_quiz <= 100):
    from openpyxl import Workbook, load_workbook
    book = load_workbook('Quiz_Problems.xlsx')
    read_sheet = book['100 Questions']
    length_row = read_sheet.max_row
    sheet = book.active

    numb_question = 1
    point = 0
    engagement = 0
    correct = 0
    while numb_question <= numb_quiz:
        randrow = random.randint(2, length_row)
        for row in read_sheet.iter_rows(randrow, randrow, min_col = 2, max_col = 2):
            print("")
            print("Question number", str(numb_question) + ":")   
            print([cell.value for cell in row]) 
            for col in read_sheet.iter_rows(min_row = randrow, max_row = randrow, min_col = 3, max_col = 3):
                print([cell.value for cell in col]) 
                break
            guest_answer = str(input("answer: "))
            answer = str("D"+str(randrow))
            correct_ans = sheet[answer].value

As you can see, to conclude what I wanted to do with the code above is to print random rows in column 3 with the random function from xslx file using python. The thing is, I wanted to prevent the random function to print the row from column 3 more than once in one run. Since again, I don’t really understand what the ‘import random’ library can actually do, perhaps there is a way to get what I wanted. Does anyone have a solution? thank you so much

P.S. Since I’m a python beginner, I also would fancy an explanation from you (so not just the code. thank you!)

Asked By: bin07

||

Answers:

So random just generates a number in that range you want. Computers don’t generate numbers totally randomly. They use a "seed" to get started. If you pass the library the same seed each time (set it via random.seed(seedNo)), it will generate the same numbers in the same order. This can be useful for testing but also defeat the purpose of generating numbers. Therefore, a common practice is getting the current time of the system and using that as the seed.

Now for making sure you don’t get the same question printed twice, I recommend you create a new empty list and each time you get a question, you add that index to the list. Then, put in a conditional checking if the index has come up before, and if it has, just pass (move on to the next iteration of the loop). The code might look like this:

askedAlready = []

    while numb_question <= numb_quiz:
        randrow = random.randint(2, length_row)
        if randrow in askedAlready: continue
        for row in read_sheet.iter_rows(randrow, randrow, min_col = 2, max_col = 2):
            print("")
            print("Question number", str(numb_question) + ":")   
            print([cell.value for cell in row]) 
            for col in read_sheet.iter_rows(min_row = randrow, max_row = randrow, min_col = 3, max_col = 3):
                print([cell.value for cell in col]) 
                break
            guest_answer = str(input("answer: "))
            answer = str("D"+str(randrow))
            correct_ans = sheet[answer].value
        askedAlready.append(randrow)

You could also rethink how you make the random generation. Make a list of all the possible question numbers then shuffle it. It won’t have any duplicates. Then you could just iterate through the shuffled list. Note that this also uses the seeding concept in the same way (random.seed())
(Inspired by thefourtheye’s answer: Generate 'n' unique random numbers within a range)

listOfRandRows = list(range(2,length_row))
random.shuffle(listOfRandRows) #this will shuffle the list "in place"
#then iterate
for i in listOfRandRows:
    #do your thing. i will be the row number randomly chosen

Edit per pjs’s recommendation: shuffling is efficient enough but rejection can take a lot of extra time. Sample is better than rejection. It’s described here: Generate 'n' unique random numbers within a range under Two-Bit Alchemist’s answer

Answered By: Acetyl-CodeA
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.