You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python读取Excel时如何避免随机函数重复选取同一行

解决随机选取Excel行重复的问题

问题根源

你当前用random.randint(2, length_row)每次随机生成行号,但没有跟踪已选过的行,所以会出现重复选取的情况。下面给你两种实用的解决方案,附带详细解释。


方案1:生成候选行列表并打乱(推荐)

这种方法先把所有可选的行号整理成列表,打乱顺序后依次取用,从根本上避免重复,效率也更高,尤其适合要选的题目数量较多的场景。

修改后的代码:

import random  # 必须导入random库,原代码遗漏了这一步
from openpyxl import Workbook, load_workbook  # 建议把导入语句放在代码开头,更规范高效

if (1 <= numb_quiz <= 100):
    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

    # 生成所有可选行号的列表(从第2行到最后一行)
    available_rows = list(range(2, length_row + 1))
    # 打乱列表顺序,实现随机排序
    random.shuffle(available_rows)

    # 遍历打乱后的列表,取前numb_quiz个行号作为题目
    for randrow in available_rows[:numb_quiz]:
        print("")
        print("Question number", str(numb_question) + ":")   
        # 读取第2列的题目内容
        for row in read_sheet.iter_rows(randrow, randrow, min_col=2, max_col=2):
            print([cell.value for cell in row]) 
        # 读取第3列的选项内容
        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
        
        numb_question += 1  # 别忘了递增题目编号

关键部分解释:

  • available_rows = list(range(2, length_row + 1)):生成从第2行到Excel最后一行的所有行号列表,确保覆盖所有可用题目。
  • random.shuffle(available_rows):原地打乱列表顺序,不需要额外变量接收返回值,直接修改原列表,实现随机排序。
  • available_rows[:numb_quiz]:取打乱后列表的前numb_quiz个元素,刚好是你需要的题目数量,且完全不会重复。

方案2:记录已选行号,重复则重新随机

这种方法适合可选题目数量远大于要选数量的场景(比如选5题但有100题),通过集合记录已选行号,每次随机后检查是否重复。

修改后的代码:

import random
from openpyxl import Workbook, load_workbook

if (1 <= numb_quiz <= 100):
    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
    selected_rows = set()  # 用集合存储已选行号,集合查询速度远快于列表

    while numb_question <= numb_quiz:
        randrow = random.randint(2, length_row)
        if randrow in selected_rows:
            continue  # 如果已经选过,跳过当前循环,重新生成随机行号
        selected_rows.add(randrow)  # 没选过就加入集合,标记为已选

        print("")
        print("Question number", str(numb_question) + ":")   
        for row in read_sheet.iter_rows(randrow, randrow, min_col=2, max_col=2):
            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
        
        numb_question += 1

关键部分解释:

  • selected_rows = set():使用集合存储已选行号,因为集合的成员查询操作(randrow in selected_rows)是O(1)时间复杂度,比列表快很多,避免频繁重复检查拖慢程序。
  • if randrow in selected_rows: continue:如果生成的行号已经被选过,直接跳过当前循环,重新生成随机数,直到拿到未选过的行号。

两种方案对比

  • 方案1:一次性生成所有随机行号,逻辑清晰,不会出现重复,适合要选的题目数量接近总题目数的场景(比如选90题但只有100题),不会出现无限循环的风险。
  • 方案2:每次随机后检查,适合要选的题目数量远小于总题目数的场景,代码改动相对小,但如果要选的数量接近总数,可能会频繁重复生成随机数,效率较低。

另外注意:你的原代码没有导入random库,运行时会报错,一定要在代码开头加上import random!

内容的提问来源于stack exchange,提问作者bin07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 00:10:37