遍历对象生成字典:键为数值,值为集合的创建与元素追加
问题:将区间对象映射到含对应data的集合字典
我正在遍历一个包含start、end、data三个int属性的对象列表,需要把start到end(包含两端)的所有数字作为字典的键,对应的值是包含该对象data的集合。例如给定对象列表:
import types objects_list = [types.SimpleNamespace(start=5, end=8, data=2), types.SimpleNamespace(start=6, end=12, data=6), types.SimpleNamespace(start=10, end=11, data=5), types.SimpleNamespace(start=20, end=22, data=4)]
期望生成的字典如下:
5: {2} 6: {2,6} 7: {2,6} 8: {2,6} 9: {6} 10: {6,5} 11: {6,5} 12: {6} 20: {4} 21: {4} 22: {4}
我尝试用下面的代码避免嵌套循环,但每次set([o.data])都会创建新集合覆盖旧值,结果不符合预期:
my_dict={} for o in objects_list: my_dict.update( dict.fromkeys(range(o.start, o.end+1), set([o.data])) )
得到的错误结果:
{5: {2}, 6: {6}, 7: {6}, 8: {6}, 9: {6}, 10: {5}, 11: {5}, 12: {6}, 20: {4}, 21: {4}, 22: {4}}
请问有没有办法实现「键不存在时创建集合,存在时向集合添加元素」,或者更合适的实现方式?
解决方案
方法1:基础字典操作(无需额外库)
直接遍历每个对象的区间范围,对每个键使用dict.get()方法获取对应集合——如果键不存在就新建空集合,然后将当前对象的data添加到集合中:
my_dict = {} for o in objects_list: for num in range(o.start, o.end + 1): # 若num不在字典中,返回空集合;否则返回已有集合 s = my_dict.get(num, set()) s.add(o.data) my_dict[num] = s
这种方式逻辑直观,不需要引入额外模块,完全符合需求。
方法2:使用collections.defaultdict简化代码
collections.defaultdict可以指定默认值类型,当访问不存在的键时会自动创建对应的空集合,代码更简洁:
from collections import defaultdict my_dict = defaultdict(set) for o in objects_list: for num in range(o.start, o.end + 1): my_dict[num].add(o.data) # 如果需要转为普通字典(可选) my_dict = dict(my_dict)
这种写法省去了手动判断键是否存在的步骤,代码更紧凑。
关于"避免嵌套循环"的说明
这里的嵌套循环无法完全避免——因为每个对象对应一个区间,区间内的每个数字都需要单独处理(要么新建集合,要么追加元素)。你之前尝试的dict.fromkeys之所以失败,是因为update操作会直接用新集合覆盖已有键的旧值,而非对原有集合进行修改,因此必须遍历区间内的每个数字来更新对应的集合。
内容的提问来源于stack exchange,提问作者Floella
相关产品推荐
相关产品推荐

