如何优化Python中嵌套读取JSON构建图书关联图的耗时
优化图书关联图构建的高效方案
原代码的问题核心是嵌套遍历整个数据集两次,时间复杂度直接拉到O(n²),5万条数据就是25亿次循环,效率必然极低。再加上每次内层循环都重复打开文件,额外增加了IO开销,必须重构。
优化思路
先按user_id分组,把每个用户读过的所有book_id收集到一起,再对每个用户的图书列表生成所有两两组合,直接添加边。这样只需要遍历数据集一次,后续的组合操作只针对每个用户的图书集合,时间复杂度会大幅降低。
优化后的代码
import jsonlines import networkx as nx from itertools import combinations G2 = nx.Graph() user_books = {} # 第一步:遍历一次文件,构建用户-图书映射 with jsonlines.open('filtered_data.json', 'r') as reader: for idx, obj in enumerate(reader, 1): user_id = obj["user_id"] book_id = obj["book_id"] # 把当前用户的图书加入对应的列表 if user_id not in user_books: user_books[user_id] = [] user_books[user_id].append(book_id) # 可选:打印进度,避免长时间无反馈 if idx % 1000 == 0: print(f"已处理 {idx} 条数据") # 第二步:遍历每个用户的图书列表,生成两两组合添加边 for books in user_books.values(): # 只有当用户读过至少2本书时才需要生成组合 if len(books) >= 2: # 用combinations生成所有不重复的两两组合 for book_pair in combinations(books, 2): G2.add_edge(*book_pair) print(f"图构建完成,节点数:{G2.number_of_nodes()},边数:{G2.number_of_edges()}")
额外优化建议
- 如果存在同一用户重复记录同一本书的情况,可以先对每个用户的
book_id去重,比如把user_books[user_id]改成集合再转列表:user_books[user_id] = list(set(user_books[user_id])),避免做无用的重复边添加操作(不过nx.Graph会自动忽略重复边,只是浪费一点计算资源)。 - 若数据集远超5万条,可以考虑结合内存映射或分块读取,但针对当前规模,上述代码足以秒级完成构建。
内容的提问来源于stack exchange,提问作者user20307062
相关产品推荐
相关产品推荐

