Python遍历列表调用remove触发ValueError: x not in list如何解决
问题说明
实现学生代码、教师代码分词结果的匹配去重逻辑时,运行触发ValueError: list.remove(x): x not in list报错,原始实现代码如下:
code_arr=[] for i in word_tokenize(student_code): code_arr.append(i) print(code_arr) print(len(code_arr)) codet_arr=[] for i in word_tokenize(teacher_code): codet_arr.append(i) print(codet_arr) print(len(codet_arr)) for code_s in code_arr: for code_t in codet_arr: if code_s==code_t: code_arr.remove(code_t) else: continue
运行后抛出的完整报错信息:
ValueError Traceback (most recent call last) <ipython-input-13-4fe8ea0c7232> in <module>() 2 for code_t in codet_arr: 3 if code_s==code_t: ----> 4 code_arr.remove(code_t) 5 else: 6 continue ValueError: list.remove(x): x not in list
代码预期逻辑:分别对student_code、teacher_code做word_tokenize分词存入两个列表,双重遍历列表,匹配到值相等的元素时从学生分词列表code_arr中移除对应元素。
报错原因
- 核心问题1:遍历列表的同时直接修改原列表,会导致索引错位。Python的for循环遍历列表是按索引从0开始依次往后取值的,一旦循环过程中调用
remove删掉元素,列表长度会立刻缩短,被删位置后面的所有元素都会向前补位,此时循环指针继续向后走就会跳过元素,甚至把已经删掉的元素判定为待删除目标。 - 核心问题2:重复token会触发重复删除。代码分词结果里必然有大量重复标识符,比如
=、print、(这类,第一次匹配到相同值时已经把code_arr里的对应元素删掉了,后续双重循环再匹配到相同值时,code_arr里已经没有对应剩余元素,直接调用remove就会抛错。 - 核心问题3:删除前没有做存在性校验。匹配逻辑里
code_t是来自教师分词列表codet_arr的值,就算和code_s值相等,也不代表当前这个值还存在于code_arr里,直接调用删除方法本身就有逻辑漏洞。
修复方案
不要在遍历原列表的时候直接执行删除操作,也没必要写低效的双重循环,根据业务需求选下面两种实现即可:
方案1:移除所有和教师代码重合的token
只要是教师代码里出现过的token,就全部从学生分词结果里移除,直接用集合做存在性判断,效率最高:
# 分词结果可以直接转列表,不需要逐元素append code_arr = list(word_tokenize(student_code)) codet_arr = list(word_tokenize(teacher_code)) # 教师分词转集合,判断元素存在的时间复杂度是O(1) teacher_tokens = set(codet_arr) # 直接通过列表推导式生成过滤后的新列表,完全避免遍历中修改原列表的问题 filtered_student_tokens = [token for token in code_arr if token not in teacher_tokens]
方案2:按重合数量精确去重
如果要保留不重合的重复token(比如学生代码里有3个for,教师代码里只有1个for,最终学生列表里保留剩下2个for,不是把所有for都删掉),用计数器实现即可:
from collections import Counter code_arr = list(word_tokenize(student_code)) codet_arr = list(word_tokenize(teacher_code)) teacher_token_count = Counter(codet_arr) filtered_student_tokens = [] for token in code_arr: if teacher_token_count.get(token, 0) > 0: teacher_token_count[token] -= 1 else: filtered_student_tokens.append(token)
内容的提问来源于stack exchange,提问作者Sharanjan Shivajokam
相关产品推荐
相关产品推荐

