Python中使用Union与嵌套循环提取字典短名称集合报错排查
问题分析与解决办法
首先来说你报错的核心原因:循环顺序搞反了!在Python的生成器表达式里,for循环的顺序要和你写嵌套for循环的逻辑一致——得先遍历外层的myDict["items"]拿到每个item,再去遍历每个item里的names列表。你原来的写法把for j in i["names"]放在了for i in myDict["items"]前面,这就导致Python还没定义i的时候,就想去访问i["names"],自然会报“i未定义”的错误。
另外还有个小问题:你names列表里的元素是集合(比如{'longName1', 'shortName1'}),不是字典,所以j.values()完全用错了——集合根本没有values()方法!根据你的预期结果,我们需要从每个集合里筛选出包含shortName的元素。
正确的Pythonic写法
最简洁的方式是用集合推导式,一步到位生成目标集合:
myDict = {'items': [{'names': [{'longName1', 'shortName1'}, {'shortName2', 'longName2'}]}, {'names': [{'longName3', 'shortName3'}, {'shortName4', 'longName4'}]}]} shortNames = {name for item in myDict["items"] for name_set in item["names"] for name in name_set if 'shortName' in name} print(shortNames) # 输出: {'shortName1', 'shortName2', 'shortName3', 'shortName4'}
如果你坚持想用set().union()的方式,也可以调整成这样:
shortNames = set().union(*( [name for name in name_set if 'shortName' in name] for item in myDict["items"] for name_set in item["names"] ))
额外优化建议
如果你的本意是把names里的元素写成字典(比如用键明确区分长名和短名,像{"long": "longName1", "short": "shortName1"}),那代码可以改成更精准的版本,不需要靠字符串判断:
myDict = {'items': [{'names': [{"long": "longName1", "short": "shortName1"}, {"long": "longName2", "short": "shortName2"}]}, {'names': [{"long": "longName3", "short": "shortName3"}, {"long": "longName4", "short": "shortName4"}]}]} shortNames = {name_dict["short"] for item in myDict["items"] for name_dict in item["names"]}
这样更严谨,也更符合字典的设计初衷。
内容的提问来源于stack exchange,提问作者ILostMySpoon
相关产品推荐
相关产品推荐

