如何高效批量更新嵌套JSON的source_filename为原文件名
高效批量更新嵌套JSON的source_filename字段
核心优化思路
已知每个JSON的顶级键均为document_*格式,无需额外判断键名,直接遍历值即可;同时利用Python内置的高效迭代工具替代纯Python循环,减少解释器开销。
方案1:极简原地修改循环(最适合中小数据量)
直接配对jsv元素与onlyfiles文件名,遍历每个JSON的所有document对象并修改字段:
for elem, filename in zip(jsv, onlyfiles): for doc in elem.values(): doc['source_filename'] = filename
优势:
- 去掉了
startswith()的字符串匹配开销,直接访问所有顶级值(都是document对象) zip()是C实现的迭代器,比手动索引访问更高效- 原地修改,无需额外内存创建新列表
方案2:用map()替代Python循环(适合中等数据量)
利用map()的C层循环加速处理:
def update_elem(args): elem, filename = args for doc in elem.values(): doc['source_filename'] = filename return elem jsv = list(map(update_elem, zip(jsv, onlyfiles)))
优势:map()的循环逻辑在C语言层面执行,比纯Pythonfor循环速度更快,尤其当jsv元素数量较多时。
方案3:多进程并行处理(适合超大数据量)
当jsv包含数十万甚至数百万个元素时,可利用多进程并行提速:
from multiprocessing import Pool def process_elem(args): elem, filename = args for doc in elem.values(): doc['source_filename'] = filename return elem # 根据CPU核心数设置进程池大小,默认用全部核心 with Pool() as pool: jsv = pool.map(process_elem, zip(jsv, onlyfiles))
注意:
- 多进程会有数据拷贝开销,仅当单个元素处理耗时较长(比如每个JSON包含大量document对象)时才划算
- 如果是IO密集型场景(比如修改后要写入文件),可改用
multiprocessing.dummy.Pool(基于线程的池)
额外优化:如果document键是连续编号
若每个JSON的document键是从document_0开始的连续编号,可直接生成键名遍历,避免遍历所有值:
for elem, filename in zip(jsv, onlyfiles): doc_count = len(elem) for k in range(doc_count): elem[f'document_{k}']['source_filename'] = filename
优势:直接定位键名,避免遍历字典所有值的开销,在document数量较多时更高效。
内容的提问来源于stack exchange,提问作者Daj
相关产品推荐
相关产品推荐

