Python循环中如何存储多组输出以统计归并排序测试耗时
问题描述
需要实现归并排序性能测试的自动化流程,测试规则如下:
- 统计归并排序算法的执行耗时
- 共测试5种不同长度的随机列表:元素量从600起步,步长100,最大到1000
- 每种列表长度下,使用10个不同的随机种子生成测试数据
- 每个随机种子对应的测试列表,重复执行10次排序测试
现有代码已经可以输出所有单次测试的耗时数值,但无法按测试轮次对结果做统计处理(包括计算均值、极差(最大值减最小值)等指标)。尝试将不同轮次的输出存入独立列表时,不知道如何在嵌套循环结构中区分不同轮次的存储对象。
原有实现代码
import time, random, statistics myseed = 0 myrange = 600 randomlist = [] random.seed(myseed) def generate_random_list(): for i in range(0,myrange): randomlist.append(random.randint(0,10000)) generate_random_list() def mergeSort(arr): if len(arr) > 1: mid = len(arr)//2 L = arr[:mid] R = arr[mid:] mergeSort(L) mergeSort(R) i = j = k = 0 while i < len(L) and j < len(R): if L[i] < R[j]: arr[k] = L[i] i += 1 else: arr[k] = R[j] j += 1 k += 1 while i < len(L): arr[k] = L[i] i += 1 k += 1 while j < len(R): arr[k] = R[j] j += 1 k += 1 arr = randomlist def procedure(): starttime = time.time() mergeSort(arr) endtime = time.time() elapsedtime = endtime - starttime print(elapsedtime) while myrange <= 1000: print(f"\n this is range {myrange}") while myseed <= 9: print(f"\n this is seed {myseed}") for x in range(0,10): procedure() myseed += 1 myrange += 100 myseed = 0
实现方案
原代码除了结果存储的问题,还有两个会导致测试结果失效的逻辑问题:
- 随机列表仅在代码初始化时生成一次,切换列表长度、切换随机种子时不会生成新的测试数据
- 排序直接在原列表上修改,同一份列表第二次执行排序时,输入已经是有序状态,测出来的耗时不具备参考价值
不需要手动创建大量独立列表存储不同轮次的结果,直接用嵌套字典按测试维度分层存储即可,三层结构刚好对应三层测试循环:第一层键为列表长度,第二层键为随机种子值,第三层存储对应条件下10次单次测试的耗时,循环执行时直接按当前遍历到的长度、种子值定位存储位置即可。
修正后的可运行代码如下:
import time import random import statistics def mergeSort(arr): if len(arr) > 1: mid = len(arr)//2 L = arr[:mid] R = arr[mid:] mergeSort(L) mergeSort(R) i = j = k = 0 while i < len(L) and j < len(R): if L[i] < R[j]: arr[k] = L[i] i += 1 else: arr[k] = R[j] j += 1 k += 1 while i < len(L): arr[k] = L[i] i += 1 k += 1 while j < len(R): arr[k] = R[j] j += 1 k += 1 # 按 列表长度->随机种子->单次耗时 三层结构存储所有测试结果 test_result = {} # 遍历所有测试的列表长度 for list_length in range(600, 1001, 100): test_result[list_length] = {} print(f"\n===== 测试列表长度:{list_length} =====") # 遍历所有随机种子 for seed in range(10): test_result[list_length][seed] = [] # 重置随机种子,生成对应长度的原始测试列表 random.seed(seed) origin_list = [random.randint(0, 10000) for _ in range(list_length)] print(f"-- 当前随机种子:{seed}") # 重复执行10次排序测试 for _ in range(10): # 每次测试使用原始列表的拷贝,避免修改原列表导致后续测试输入失真 sort_input = origin_list.copy() # 用perf_counter统计短耗时精度比time.time()更高 start_time = time.perf_counter() mergeSort(sort_input) elapsed = time.perf_counter() - start_time test_result[list_length][seed].append(elapsed) print(f"单次耗时:{elapsed:.6f}s") # 计算当前种子下的统计指标 seed_costs = test_result[list_length][seed] seed_avg = statistics.mean(seed_costs) seed_range = max(seed_costs) - min(seed_costs) print(f"种子{seed}统计结果:平均耗时{seed_avg:.6f}s,极差{seed_range:.6f}s") # 计算当前列表长度下的整体统计指标 all_costs = [cost for seed_res in test_result[list_length].values() for cost in seed_res] length_avg = statistics.mean(all_costs) length_range = max(all_costs) - min(all_costs) print(f"长度{list_length}整体统计:平均耗时{length_avg:.6f}s,极差{length_range:.6f}s")
关键改动说明:
- 嵌套字典的存储结构不需要提前手动创建大量独立列表,循环过程中可以直接按当前遍历的维度定位存储位置,取数做统计时也可以按维度灵活筛选
- 修复了原代码的测试逻辑漏洞,每次换种子重新生成测试列表,每次排序使用原始列表的独立拷贝,保证每次测试的输入一致
- 替换计时函数为
time.perf_counter(),短耗时场景下统计精度更高 - 每跑完一个测试维度就自动计算均值、极差,需要新增标准差、中位数等统计指标时,直接调用
statistics模块对应函数即可。
内容的提问来源于stack exchange,提问作者racoonfused
相关产品推荐
相关产品推荐

