Python使用csv.DictReader嵌套遍历CSV时内层循环不复位如何解决
问题原因
是的,该问题正是csv.DictReader的迭代特性导致的。csv.DictReader属于一次性迭代器,遍历完成后底层文件指针已经移动到文件末尾,后续再次遍历不会返回任何内容,所以外层循环第二次执行时,内层的reader2已经没有可迭代的元素,直接跳过循环。
修复方案
针对不同的使用场景,有三种常见的修复方式:
- 方案1:提前读取小表内容到内存(推荐绝大多数场景使用)
如果csv2文件体积不大,可以提前把所有内容读取到列表中,列表支持反复遍历,不会出现迭代器耗尽的问题。
代码示例:
import csv with open('csv1.csv', 'r') as inFile1: with open('csv2.csv', 'r') as inFile2: reader1 = csv.DictReader(inFile1) # 提前读取csv2所有行到列表 reader2_rows = list(csv.DictReader(inFile2)) for row1 in reader1: for row2 in reader2_rows: if row1['key1'] == row2['key2']: # 此处执行自定义操作 pass
- 方案2:重置文件指针(适合大文件场景)
如果csv2体积过大无法全部载入内存,可以每次外层循环时将文件指针复位到开头,重新生成reader2遍历:
代码示例:
import csv with open('csv1.csv', 'r') as inFile1: with open('csv2.csv', 'r') as inFile2: reader1 = csv.DictReader(inFile1) # 先读取csv2的表头备用 csv2_fields = csv.DictReader(inFile2).fieldnames for row1 in reader1: # 复位文件指针到文件起始位置 inFile2.seek(0) # 重新生成reader2,跳过表头行 reader2 = csv.DictReader(inFile2, fieldnames=csv2_fields) next(reader2) for row2 in reader2: if row1['key1'] == row2['key2']: # 此处执行自定义操作 pass
- 方案3:构建索引优化查询效率(推荐有关联匹配需求的场景)
嵌套循环的时间复杂度是O(n*m),数据量大时性能很差。可以提前用关联键构建csv2的索引字典,把时间复杂度降到O(n+m):
代码示例:
import csv # 提前构建csv2的索引 csv2_index = {} with open('csv2.csv', 'r') as inFile2: for row in csv.DictReader(inFile2): key = row['key2'] csv2_index.setdefault(key, []).append(row) # 遍历csv1直接匹配索引 with open('csv1.csv', 'r') as inFile1: for row1 in csv.DictReader(inFile1): matched_rows = csv2_index.get(row1['key1'], []) for row2 in matched_rows: # 此处执行自定义操作 pass
内容的提问来源于stack exchange,提问作者jf21
相关产品推荐
相关产品推荐

