仅已知父节点时将扁平列表转换为层级嵌套字典的实现方案
如何将带父/子关系的扁平列表转换为嵌套字典结构?
我明白你现在的困扰——从Scryfall的API拿到的扁平集合数据,只有父集合编码,没有子集合信息,要转成和官网一样的层级结构确实有点棘手,尤其是当列表里先出现深层节点的时候。别担心,我们可以用自底向上+哈希表映射的方式来解决这个问题,比自顶向下的方法更灵活,不管节点出现顺序如何都能处理。
核心思路
这个方法的关键是先把所有节点“存起来”,再逐个关联父/子关系:
- 先用哈希表(Python字典)把所有节点按唯一标识(比如集合编码、示例里的
name)映射好,这样能在O(1)时间内找到任意节点 - 遍历每个节点,如果它有父节点,就把它添加到父节点的
children列表中;如果没有父节点,就把它归为根节点 - 最后收集所有根节点,就是我们需要的层级嵌套结构
示例代码实现(针对你的人员数据)
下面是针对你给出的人员示例的可运行代码,完全符合你想要的输出:
def build_hierarchy(items, id_key="name", parent_key="parent", children_key="children"): # 第一步:创建哈希表,用唯一标识映射所有节点 item_map = {item[id_key]: item for item in items} # 初始化根节点列表 roots = [] for item in items: parent_id = item.get(parent_key) if parent_id: # 找到对应的父节点,将当前节点加入其children列表 parent_item = item_map.get(parent_id) if parent_item: # 如果父节点还没有children字段,先初始化 if children_key not in parent_item: parent_item[children_key] = [] parent_item[children_key].append(item) else: # 没有父节点,直接加入根节点列表 roots.append(item) return roots # 测试你的人员数据 people = [ { "name" : "a" }, { "name": "b", "parent" : "a"}, { "name": "c", "parent" : "a"}, { "name": "d", "parent" : "b"}, { "name": "e", "parent" : "d"}, ] sorted_people = build_hierarchy(people) print(sorted_people)
运行这段代码后,输出结果和你期望的完全一致。而且哪怕你把e或者d放在列表的最前面,结果也不会出错——因为哈希表已经提前存储了所有节点,找父节点不受遍历顺序影响。
适配Scryfall的集合数据
针对Scryfall的API返回数据,只需要调整几个参数就能复用上面的函数:
id_key用code(集合的唯一编码)parent_key用parent_set_code(API返回的父集合编码字段)
适配后的代码示例:
import requests def build_scryfall_set_hierarchy(): # 获取Scryfall的集合数据 response = requests.get("https://api.scryfall.com/sets") sets_data = response.json()["data"] # 调用通用层级构建函数,适配Scryfall的字段 return build_hierarchy( sets_data, id_key="code", parent_key="parent_set_code", children_key="children" ) # 获取并打印层级化的万智牌集合 hierarchical_sets = build_scryfall_set_hierarchy()
为什么这个方法更适合你的场景?
- 无需提前定位根节点:不管扁平列表里先出现哪个层级的节点,哈希表都能快速找到它的父节点,完全解决了“首个元素是孙节点”的问题
- 效率更高:整个过程的时间复杂度是O(n)(n为节点数量),比自顶向下递归查找父节点的方法效率高很多
- 通用性强:只需要修改几个参数,就能适配任何带父/子关联的扁平数据结构
内容的提问来源于stack exchange,提问作者erotski
相关产品推荐
相关产品推荐

