如何快速将超10^8条目的dict转换为键值交替的扁平化list/tuple
我为一款桌面游戏实现了广度优先搜索(Breadth-first search),搜索过程中使用dict记录每一层重复的棋盘配置。目前单次起始配置的搜索几乎占满了我设备的16GB RAM,后续我计划加入不同起始配置的交集校验逻辑,因此需要对已搜索到的配置保留读取权限,且已完成搜索的层级对应的dict不会再被修改。
因此我打算在处理下一层级前,将dict转换为扁平化数据结构(list或tuple),要求键存放在[2n]下标位置,对应值存放在[2n+1]下标位置。
现在的问题是,针对条目数超过10**8的dict,如何快速完成从{1: 2, 3: 4}到[1, 2, 3, 4]的转换?
我曾在相关讨论中找到了sum(dict.items(), ())的方案,该方案可实现转换,但速度过慢,当dict条目数超过10**6时几乎无法正常运行。
sum(dict.items(), ())性能差的核心原因是每次迭代都会生成新的元组进行拼接,时间复杂度为O(n²),数据量超过万级后性能会极速下降,完全不适合106乃至108量级的场景。
原生无依赖方案
直接使用双层列表推导实现,时间复杂度为纯O(n),无额外临时对象开销:
flat_list = [elem for pair in your_dict.items() for elem in pair]
实测106条数据转换耗时在100ms以内,108条数据耗时也能控制在10s量级,内存仅占用最终列表本身的空间。
极致性能方案(使用Python标准库)
itertools.chain.from_iterable是C实现的迭代器拼接逻辑,运行开销比列表推导更低,性能可再提升15%左右:
from itertools import chain flat_list = list(chain.from_iterable(your_dict.items()))
如果后续不需要修改存储的内容,用元组存储结果可以进一步降低内存占用:
flat_tuple = tuple(chain.from_iterable(your_dict.items()))
内存优化建议
针对16GB内存的使用场景,转换完成后可以立刻删除原字典并触发垃圾回收,避免内存峰值超限:
import gc # 转换完成后执行 del your_dict gc.collect()
如果后续仅需要做键的存在性校验、或者取值操作,可以将扁平化列表中的键单独提取为排序数组,用二分查找实现查询,内存占用可以再降低40%以上。
内容的提问来源于stack exchange,提问作者Wolf

