【问题标题】:Recursively find all the parents of a child given list of dictionaries递归查找给定字典列表的孩子的所有父母
【发布时间】:2021-04-26 22:54:59
【问题描述】:

给定一个字典列表如下:

[{'id': '1', 'parents': []},
 {'id': '2', 'parents': ['1']},
 {'id': '3', 'parents': ['1', '2']},
 {'id': '4', 'parents': ['3']},
 {'id': '5', 'parents': ['1', '2', '3', '4']},
 {'id': '6', 'parents': ['4', '5']},
 {'id': '7', 'parents': ['4']},
 {'id': '8', 'parents': []},
 {'id': '9', 'parents': ['1', '8']},
 {'id': '10', 'parents': ['8']},
 {'id': '11', 'parents': ['5', '6']}]

我想构建一个函数,以递归方式结束所有元素的所有父元素。

例如元素 11 有两个父元素 5 和 6,它们也分别有 ['1', '2', '3', '4'] 和 ['4','5'] 也有.. .. 所以在这种情况下 11 的总父母是 [1,2,3,4,5,6]

我是这样开始的:

def total_parents(parentlist,tree):
    if parentlist == []:
        return
    total = []
    for parent in parentlist:
        total.append(next((element['parents'] for element in tree if element['id'] == parent), None))
    total_flatten = [item for sublist in total for item in sublist]
    total_flatten_set = list(set(total_flatten))
    return total_parents(total_flatten_set,tree)

for claim in tree:
    claim['total_parents'] = total_parents(claim['parents'],tree)

这根本不起作用。在玩了很多代码并查看了一些递归问题之后:How to recursively generate a list of parent-child strings from an Adjacency List?

【问题讨论】:

  • /questions/8673482/transitive-closure-python-tuples 有帮助吗?了解transitive closure这个词有帮助吗?

标签: python recursion tree parent-child


【解决方案1】:

给定一个字典如下:

您的输入不是字典。它是一个 list 包含 2 元素字典(包含大量冗余信息)。如果您可以重新格式化您的输入,那么您正在寻找的功能非常简单。

如果您的输入是以下形式的字典,您可以通过以下方式构造函数:{<id>: [<parents>]}:

parent_map ={
    '1': [],
    '2': ['1'],
    '3': ['1', '2'],
    '4': ['3'],
    '5': ['1', '2', '3', '4'],
    '6': ['4', '5'],
    '7': ['4'],
    '8': [],
    '9': ['1', '8'],
    '10': ['8'],
    '11': ['5', '6']}

def get_parents(parent_map, node_id):
    parents = set(parent_map[node_id])
    for parent_id in parent_map[node_id]:
        parents |= set(get_parents(parent_map, parent_id))
    return list(parents)

以下是如何将原始输入数据转换为上述函数中使用的格式:

single_dict = {x['id']: x['parents'] for x in list_of_dicts}

输入数据的形状和格式会对您对其进行操作的效率产生巨大影响。

【讨论】:

  • 符号 |= 到底在做什么?谢谢。
  • parents 是一个集合 (documentation)。 |= 运算符采用参数和parents 的集合并集并将结果分配给parents
【解决方案2】:

您可以使用递归生成器函数:

data = [{'id': '1', 'parents': []}, {'id': '2', 'parents': ['1']}, {'id': '3', 'parents': ['1', '2']}, {'id': '4', 'parents': ['3']}, {'id': '5', 'parents': ['1', '2', '3', '4']}, {'id': '6', 'parents': ['4', '5']}, {'id': '7', 'parents': ['4']}, {'id': '8', 'parents': []}, {'id': '9', 'parents': ['1', '8']}, {'id': '10', 'parents': ['8']}, {'id': '11', 'parents': ['5', '6']}]
d = {i['id']:i for i in data}
def get_ids(_id, c = []):
   yield from d[_id]['parents']
   for i in filter(lambda x:x not in c+[_id], d[_id]['parents']):
      yield from get_ids(i, c+[_id])

r = [{**i, 'total_parents':sorted(set(get_ids(i['id'])))} for i in data]

输出:

[{'id': '1', 'parents': [], 'total_parents': []}, 
 {'id': '2', 'parents': ['1'], 'total_parents': ['1']}, 
 {'id': '3', 'parents': ['1', '2'], 'total_parents': ['1', '2']}, 
 {'id': '4', 'parents': ['3'], 'total_parents': ['1', '2', '3']}, 
 {'id': '5', 'parents': ['1', '2', '3', '4'], 'total_parents': ['1', '2', '3', '4']}, 
 {'id': '6', 'parents': ['4', '5'], 'total_parents': ['1', '2', '3', '4', '5']}, 
 {'id': '7', 'parents': ['4'], 'total_parents': ['1', '2', '3', '4']}, 
 {'id': '8', 'parents': [], 'total_parents': []}, 
 {'id': '9', 'parents': ['1', '8'], 'total_parents': ['1', '8']}, 
 {'id': '10', 'parents': ['8'], 'total_parents': ['8']}, 
 {'id': '11', 'parents': ['5', '6'], 'total_parents': ['1', '2', '3', '4', '5', '6']}]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多