如何编写递归函数遍历ROR父关系链识别美国联邦资助机构
问题描述
我正在筛选一批资助机构列表,只保留美国联邦资助机构。每个机构用ROR ID标识,通过ROR REST API获取详情。需要编写递归函数,逐级追溯机构的所有parent关系,直到顶级节点,判断顶级节点是否为“Government of the United States of America”(ROR ID:https://ror.org/02rcrvv70)。
举个例子:特拉华太空资助项目的关系链是特拉华太空资助项目→NASA→美国政府,共两层。函数需要先尝试第一个parent(NASA),递归追溯;如果这条路径走不通,就返回尝试下一个parent(比如特拉华大学)。
现在的困惑是:如何确保遍历所有可能的分支路径?如何跟踪当前分支,在路径不通时切换到其他分支?
现有代码如下:
import requests url = 'https://api.ror.org/organizations/010jszw77' api_response = requests.get(url) parsed_response = api_response.json() num_relationships = len(parsed_response['relationships']) # 2 relationships in this example, both parents print(f"Found {num_relationships} relationships") for i in range(0, num_relationships): if(parsed_response['relationships'][i]['type']) == "Parent": print("parent") if parsed_response['relationships'][i]['label'] = "Government of the United States of America": USFF = True else: run_up_chain_to_USGovt(parsed_response['relationships'][i]['id']) #kick off recursive run up the chain else: 1 #not a parent, do nothing def run_up_chain_to_USGovt(rorid): # get passed a ROR ID # see if it has a parent of USGovt # if not, investigate a parent and so on local_url = 'https://api.ror.org/organizations/' + rorid local_api_response = requests.get(local_url) local_parsed_response = local_api_response.json() # local_parsed_response['relationships'] is a new list. Have to keep track of which index we're on # if the first parent isn't USGovt, try the id of that one. Call run_up_chain_to_USGovt again #eventually, if no more parents #if local_parsed_response['id'] == https://ror.org/02rcrvv70 # USGovt # Found a path to top level USGovt #else: # No path to USGovt # Go back to the start and try a different parent return
解决方案
核心思路
要遍历所有分支并正确回溯,需让递归函数返回布尔值:找到美国政府则返回True,否则遍历当前机构的所有parent,只要有一个分支返回True,当前函数就返回True;所有分支都走不通则返回False。同时加入已访问节点缓存,避免重复查询和循环递归。
完整代码实现
import requests # 美国政府的ROR ID US_GOV_ROR_ID = "https://ror.org/02rcrvv70" # 缓存已查询过的机构,避免重复请求和循环引用 visited = set() def is_us_federal_agency(ror_id): # 提取ROR ID的最后一段(API只需要末尾的标识符) ror_short_id = ror_id.split('/')[-1] # 避免重复查询同一机构 if ror_short_id in visited: return False visited.add(ror_short_id) # 请求机构详情 url = f"https://api.ror.org/organizations/{ror_short_id}" response = requests.get(url) if response.status_code != 200: print(f"无法获取机构信息:{ror_id}") return False org_data = response.json() # 检查当前机构是否为美国政府 if org_data['id'] == US_GOV_ROR_ID: return True # 遍历所有parent关系,递归检查每个分支 for rel in org_data['relationships']: if rel['type'] == "Parent": parent_ror_id = rel['id'] if is_us_federal_agency(parent_ror_id): return True # 所有分支都未找到美国政府 return False # 测试:特拉华太空资助项目 test_ror_id = "https://ror.org/010jszw77" print(f"该机构是否为美国联邦资助机构:{is_us_federal_agency(test_ror_id)}")
关键细节说明
- 分支遍历与回溯:递归函数会逐个尝试当前机构的所有parent分支,只要某个分支找到美国政府,就立即返回
True;如果当前分支走不通,自动回到上一层,继续尝试下一个分支。 - 缓存机制:用
visited集合记录已查询的机构短ID,避免重复请求API,同时防止机构间循环引用导致无限递归(比如A的parent是B,B的parent是A的极端情况)。 - API请求优化:提取ROR ID的最后一段作为请求参数,符合API的调用规范,避免传递完整URL可能导致的错误。
内容的提问来源于stack exchange,提问作者eschares
相关产品推荐
相关产品推荐

