【问题标题】:Python - Mapping job dependencies in tree structurePython - 在树结构中映射作业依赖项
【发布时间】:2014-10-05 00:57:50
【问题描述】:

我有具有依赖项及其状态的作业列表。我想遍历每项工作并将它们的依赖关系映射为树。树的末端将是两个父依赖项的状态都已完成 - 这意味着遍历应该停止。我不确定是否应该使用递归,或者这是否真的是唯一的可能性。是否有可以帮助我的本地映射工具或数据结构?我将迭代近 1 万个工作。

伪代码

def map_depends(job_depends):
    for job in job_depends:
        if job.status = done:
            job_tree_map.append(job.name)
        else:
            map_depends(job.get('dependencies'))

def main():       
    for job in batch:
                if job.get('dependencies'):
                    map_depends(job.get('dependencies'))

我正在谈论的内容的视觉描述。

         -> job_depends1.status = done
main_job                                              -> job_depends3 = running -> job_depends6 = done
         -> job_depends2 = running......job_depends2  -> jon_depends4 = done
                                                      ->  job_depends5 = done

【问题讨论】:

  • 您的代码看起来有点不一致:job vs jobs, job.get(depends) vs job.get('dependencies')
  • 谢谢。进行了更正。

标签: python python-2.7 tree mapping


【解决方案1】:

树是自然递归的数据结构,但是,任何可以递归编写的东西都可以使用显式堆栈迭代完成。

很遗憾,在 CPython 3.[34] 之前,您无法获得“yield from”,这使得递归生成器在早期版本中变得不切实际。

因此,如果您仍然以 2.7 为目标,您可能应该先以递归方式编写内容,让它们以这种方式工作,然后以非递归方式执行您的生成器。

对于堆栈,许多 Python 开发人员会在列表或 acollections.deque 上使用 append 和 pop。为了抽象起见,我可能会使用http://stromberg.dnsalias.org/~strombrg/linked-list/,尽管这在 CPython 中通常很慢。

【讨论】:

    【解决方案2】:

    如果你的树相当深,使用递归算法可能会导致堆栈溢出,因为默认情况下 CPython 有 1000 个嵌套调用的限制。您可以使用sys.setrecursionlimit 设置自己的限制值,但通常不建议这样做。因此,在您的情况下,以迭代方式重写树遍历可能会更好。

    例如,您可以编写一个类似于树过滤和遍历的函数(不是伪代码):

    def walkjob(job):
        if job is None:
            return []
    
        result = [job, ]
        cursor = 0
    
        while cursor < len(result):
            job = result[cursor]
            result.extend(list(
                filter(lambda j: j.done,
                job.children)))
            cursor += 1
    
        return result
    

    这里是它在 REPL 中的用法:

    >>> from bunch import Bunch
    >>> job = Bunch(value=1, done=True, children=[
    ...           Bunch(value=2, done=True, children=[]),
    ...           Bunch(value=3, done=True, children=[
    ...               Bunch(value=4, done=False, children=[]),
    ...               Bunch(value=5, done=True, children=[])])])
    ...
    >>> map(lambda j: (j.value, j.done), walkjob(job))
    [(1, True), (2, True), (3, True), (5, True)]
    

    可能相关的问题:

    【讨论】:

    • 如果我的脚本导致堆栈溢出会怎样?它会关闭服务器吗?这可以包含吗?
    • 如果堆栈溢出,您的代码将抛出RuntimeError: maximum recursion depth exceeded 错误。与任何其他异常一样,除非被捕获(此异常在 Python 中可捕获),否则它会导致您的应用程序停止运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    • 2015-11-04
    • 2013-02-16
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多