从多字典列表中条件提取数据的最优Python实现方案
从两个TAP数据源补全行星数据的优化方案
问题背景
需要通过两个TAP接口从不同数据库获取数据来构建行星对象,规则是以第一个数据源的结果为主,当字段值缺失时,从第二个数据源提取对应字段补充。但两个数据源的字段名不匹配,无法直接通过字典交集来处理。
初始冗余实现
最初的代码可以正常运行,但存在大量重复逻辑,维护性差:
for result in eeuresults: name=result['target_name'] axes=result['semi_major_axis'] period=result['period'] radius=result['radius'] if math.isnan(period): for r in eparesults: if r['pl_name'] == name: period=r['pl_orbper'] if math.isnan(axes): for r in eparesults: if r['pl_name'] == name: axes=r['pl_orbsmax'] if math.isnan(radius): for r in eparesults: if r['pl_name'] == name: radius=r['pl_radj']
尝试简化的误区
曾尝试用dict.get()简化代码,但当第二个数据源没有对应匹配项时,列表推导式会抛出索引越界错误,无法处理空结果的情况:
axes=result.get('semi_major_axis',[r['pl_orbper'] for r in eparesults if r['pl_name']==name][0])
最终优化方案
通过提取辅助函数search_epa封装重复的查找逻辑,大幅减少代码冗余,同时提升了可读性和可扩展性。完整实现如下:
def getsystemdata(name, epaname=None): def search_epa(name, value, key): if math.isnan(value): for r in eparesults: if r['pl_name'] == name: return r[key] return value if epaname == None: epaname=name service=pyvo.dal.TAPService("https://exoplanetarchive.ipac.caltech.edu/TAP") eparesults=service.search(f"select pl_name, pl_radj, pl_orbper, pl_orbsmax from pscomppars where hostname = '{epaname}' ") service=pyvo.dal.TAPService("http://voparis-tap-planeto.obspm.fr/tap") eeuresults=service.search(f"select target_name, radius, period, semi_major_axis from exoplanet.epn_core where star_name = '{name}'") planets=[] for result in eeuresults: name=result['target_name'] axes=search_epa(name, result['semi_major_axis'], 'pl_orbsmax') period=search_epa(name, result['period'], 'pl_orbper') radius=search_epa(name, result['radius'], 'pl_radj') planets.append(Planet(name.split(' ')[-1], axes, period, radius)) return planets
内容的提问来源于stack exchange,提问作者tautology
相关产品推荐
相关产品推荐

