Python使用csvreader比对两个CSV文件时内层循环不执行问题求助
问题根因
- csv.reader是单向迭代器,你在循环外初始化了
drop_csvreader,第一次外层循环遍历完所有drop文件的行之后,迭代器就被耗尽了,后续外层循环的内层遍历自然无内容可走。如果连第一次内层循环都没进入,大概率是你在执行这段循环代码前,已经提前读取过一次drop_csvreader的内容,导致迭代器已经为空。 - 另外你当前的双重循环写法时间复杂度是O(n*m),两个文件行数多的话性能会非常差。
解决方法
方案1:预加载drop文件内容到内存(推荐,性能更优)
提前把drop文件里的所有行存为列表,后续外层循环直接用内存数据匹配即可,不会出现迭代器耗尽的问题。
示例代码:
import csv # 先预加载drop文件的所有行到列表 drop_rows = [] with open(drop_feed_modified, "r", encoding="utf-8") as f: drop_csvreader = csv.reader(f) drop_rows = list(drop_csvreader) with open(enroll_feed_modified, "r", encoding="utf-8") as f: enroll_csvreader = csv.reader(f) for row in enroll_csvreader: print(row[1]) # 直接遍历内存中的drop行列表 for row_1 in drop_rows: print("inside second loop") if row[1] == row_1[1] and row[3] == row_1[3]: print(*row_1, sep="|")
方案2:每次外层循环重置drop文件指针
如果drop文件太大无法全部加载进内存,可以每次外层循环前把drop文件的指针重置到开头,重新生成reader即可:
import csv enroll_file_read = open(enroll_feed_modified, "r", encoding="utf-8") drop_file_read = open(drop_feed_modified, "r", encoding="utf-8") enroll_csvreader = csv.reader(enroll_file_read) for row in enroll_csvreader: print(row[1]) # 每次重置文件指针到开头 drop_file_read.seek(0) drop_csvreader = csv.reader(drop_file_read) for row_1 in drop_csvreader: print("inside second loop") if row[1] == row_1[1] and row[3] == row_1[3]: print(*row_1, sep="|") # 手动关闭文件,也可以用with语句自动管理文件生命周期 enroll_file_read.close() drop_file_read.close()
性能优化方案
如果文件行数较多,可以把drop文件的匹配键(第二列+第三列的组合)作为字典的key,整行作为value,单次遍历drop文件构建字典,后续遍历enroll文件的时候直接查字典即可,时间复杂度可以降到O(n+m):
import csv drop_map = {} with open(drop_feed_modified, "r", encoding="utf-8") as f: for row in csv.reader(f): # 用需要匹配的两个字段组合作为唯一key match_key = (row[1], row[3]) drop_map[match_key] = row with open(enroll_feed_modified, "r", encoding="utf-8") as f: for row in csv.reader(f): current_key = (row[1], row[3]) if current_key in drop_map: print(*drop_map[current_key], sep="|")
内容的提问来源于stack exchange,提问作者Prasanna K
相关产品推荐
相关产品推荐

