【问题标题】:How do I turn this into a recursive function?如何将其转换为递归函数?
【发布时间】:2018-04-28 05:53:13
【问题描述】:

我正在尝试基于一个模型创建一个组织结构图,该模型通过一个名为reports_to 的属性引用自身。我不知道组织结构图会下降多少层,所以我觉得递归函数很有意义。下面是一些目前有效的代码:

top_level = Person.objects.filter(reports_to=None)
org_chart = {}
for person in top_level:
    org_chart[person] = {}
    if person.has_direct_reports():
        direct_reports = Person.objects.filter(reports_to=person)
        for p in direct_reports:
            org_chart[person][p] = {}
            if p.has_direct_reports():
                direct_reports_2 = Person.objects.filter(reports_to=p)
                for q in direct_reports_2:
                    org_chart[person][p][q] = {}
                        # ... and so on

这会产生这样的 shell 输出:

>>> pp.pprint(org_chart)
{   <Person: Joe Boss>: {   <Person: John Doe>: {   <Person: John Doe Jr>: {   },
                                                          <Person: Jane Doe>: {   }}},
    <Person: Partner Mary>: {}}

这是正确的。显示清洁剂:

Joe Boss
- John Doe
-- John Doe Jr
-- Jane Doe
Partner Mary

我一直在尝试将此代码转换为递归函数,但我的大脑无法解决这个问题。感谢您提供解决此问题的任何建议或帮助!

编辑。这是我正在尝试制作的代码,但在此过程中我陷入了困境:

def direct_reports_r(person):
    if person.has_direct_reports():
        direct_reports = Person.objects.filter(reports_to=person)
        for person in direct_reports:
            org_chart[person] = {}
            if person.has_direct_reports():
                direct_reports = Person.objects.filter(reports_to=person)
                org_chart[person] = direct_reports_r(person)
            else:
                return person
    else:
        return False

top_level = Person.objects.filter(reports_to=None)
org_chart = {}
for person in top_level:
    org_chart[person] = {}
    # recursion
    org_chart[person][direct_reports_r(person)] = {}

【问题讨论】:

  • 听起来像图形搜索(编辑:实际上是的,它只是树遍历,因为没有循环)。无论如何,如果你重构 Person 会更容易,所以它有一个 direct_reports 属性/方法 - 与 reports_to 的方向相反,但可能是一对多的。然后if person.has_direct_reports(); direct_reports = Person.objects.filter(reports_to=person); for p2 in direct_reports也简化为for p2 in person.direct_reports()
  • 我还没有听说过图搜索或树!这么多学习去做。谢谢。
  • 您的代码中有一个错误:您重新声明了for person in direct_reports,但这会掩盖调用它的person。最好叫它subordinatedrp2 或其他任何名称

标签: python recursion graph


【解决方案1】:

我希望这段代码有效。

def foo(person, tmp_root):
    tmp_root[person] = {}
    if person.has_direct_reports():
        direct_reports = Person.objects.filter(reports_to=person)
        for p in direct_reports:
            foo(p, tmp_root[person])

org_chart = {}
top_level = Person.objects.filter(reports_to=None)
for person in top_level:
    foo(person, org_chart)

【讨论】:

    【解决方案2】:

    传递的列表和字典一样是可变的,所以当你将它传递给参数时,它是通过引用。这是一个示例,您可以使用它来实现所需的结果。

    top_level = Person.objects.filter(reports_to=None)
    org_chart = {}
    
    def init_org_chart(reports, arg):
        for person in reports:
            arg[person] = {}
            if person.has_direct_reports():
                direct_reports = Person.objects.filter(reports_to=person)
                init_org_chart(direct_reports, arg[person])
    
    init_org_chart(top_level, org_chart)
    

    【讨论】:

    • 我在想将org_chart 传递给递归可能会起作用。让我消化一下,但它对我有用!
    • 这个答案的两个版本都对我有用。我喜欢这个版本将所有内容都放入函数中,而不是在函数之外添加任何 for 循环。谢谢!
    猜你喜欢
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 2020-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-18
    相关资源
    最近更新 更多