CS50 Problem Set 6 DNA加载大型数据库时报IndexError索引越界
问题现象
- 执行命令
python dna.py databases/large.csv sequences/10.txt时触发运行时错误 - Traceback指向代码第47行
check[i][j] = False,抛出IndexError: list index out of range异常 - 该异常仅在加载大型数据库时触发,小型数据库运行完全正常
- 已初步定位疑似问题范围为代码中标注
Check database for matching profiles的40-49行代码段
错误根因
核心问题出在check二维列表的初始化逻辑,存在两个致命错误:
- 列表维度完全写反
原初始化代码为:
这段代码生成的二维列表,外层长度等于STR种类数(大型数据库共8种STR,小型数据库仅3种),内层长度等于数据库人员条目数。但后续循环逻辑是外层遍历人员索引check = [[0]*len(database)]*len(STRs)i in range(len(database))、内层遍历STR索引j in range(len(STRs)),预期check[i]存储第i个人员的所有STR匹配结果。
小型数据库人员条目数少于等于STR种类数时,i的取值不会超过外层列表长度,不会触发越界;大型数据库人员条目数远大于STR种类数,当i遍历到超过STR种类数的索引时,直接访问不存在的外层列表位置,触发索引越界错误。 - 浅拷贝逻辑bug
Python中对存储引用类型的列表使用*做乘法时,生成的所有内层列表都是同一个内存对象的引用,就算修正了维度问题,修改任意一行的元素值时所有行的对应位置都会同步变更,最终匹配逻辑会完全错误。
修复方法
将原check列表初始化代码替换为维度正确、无浅拷贝问题的写法:
check = [[False]*len(STRs) for _ in range(len(database))]
可选优化:该场景下完全不需要维护二维check数组,遍历人员时逐STR比对,遇到不匹配直接终止当前人员的比对即可,逻辑更简洁、内存占用更低,参考实现如下:
match = None for person_idx in range(len(database)): profile_match = True for str_idx in range(len(STRs)): if matches[STRs[str_idx]] != int(database[person_idx][STRs[str_idx]]): profile_match = False break if profile_match: match = person_idx break
内容的提问来源于stack exchange,提问作者strzelec11
相关产品推荐
相关产品推荐

