如何以递归方式检查文件数组是否包含其他依赖项的依赖项?

时间:2010-08-10 12:48:18

标签: php recursion include dependencies

为了解释我的问题,让我首先指出这个数组:

<?php
$_depends = array(
    '/Scripting/jquery.hyponiqs/jquery.dropdown.js' => array(
        "/Scripting/jquery.externals/jquery.resize.js",
        "/Scripting/jquery.externals/jquery.topzindex.js",
        "/Scripting/jquery.externals/jquery.timers.js",
        "/Scripting/jquery-ui.min.js",
        "/Scripting/jquery.hyponiqs/hyponiqs.core.js",
    ),
    '/Script/UI/Dialogs.js' => array(
        "/Scripting/jquery.externals/jquery.resize.js",
        "/Scripting/jquery.externals/jquery.topzindex.js"
    ),
    '/Script/Display/List.js' => array(
        "/Scripting/jquery.externals/jquery.timers.js"
    )
);
?>

每当包含JavaScript文件时,都会针对此数组检查依赖项。然后将每个文件的所有依赖项添加到最终的$includes数组中。当我添加带有依赖项的include时,问题就来了,其中一个依赖项也有自己的依赖项,例如:

<?php
$_depends = array(
    '/Scripting/jquery.hyponiqs/jquery.dropdown.js' => array(
        "/Scripting/jquery.externals/jquery.resize.js",
        "/Scripting/jquery.externals/jquery.topzindex.js",
        "/Scripting/jquery.externals/jquery.timers.js",
        "/Scripting/jquery-ui.min.js",
        "/Scripting/jquery.hyponiqs/hyponiqs.core.js",
    ),
    '/Script/UI/Dialogs.js' => array(
        "/Scripting/jquery.externals/jquery.resize.js",
        "/Scripting/jquery.externals/jquery.topzindex.js"
    ),
    '/Script/Display/List.js' => array(
        "/Scripting/jquery.externals/jquery.timers.js"
    ),
    '/Script/UI/Calendar/Main.js' => array(
        "/Scripting/jquery-ui.min.js",
        "/Script/UI/Dialogs.js"
    )
);
?>

正如您所看到的,添加的'/Script/UI/Calendar/Main.js'取决于"/Script/UI/Dialogs.js",它具有自己的依赖关系。

我知道我必须以递归方式检查依赖数组和最终包含数组,但我似乎无法绕过逻辑。这里的一点帮助可能会很好。

更新

我将所有内容都包装在一个类中以说明其目的(尽管实际的类更复杂并且具有各种其他包含处理功能:

<?php
class Script_Depends {
    private $_includes = array();

    private $_depends = array(
        '/Scripting/jquery.hyponiqs/jquery.dropdown.js' => array(
            "/Scripting/jquery.externals/jquery.resize.js",
            "/Scripting/jquery.externals/jquery.topzindex.js",
            "/Scripting/jquery.externals/jquery.timers.js",
            "/Scripting/jquery-ui.min.js",
            "/Scripting/jquery.hyponiqs/hyponiqs.core.js",
        ),
        '/Script/UI/Dialogs.js' => array(
            "/Scripting/jquery.externals/jquery.resize.js",
            "/Scripting/jquery.externals/jquery.topzindex.js"
        ),
        '/Script/Display/List.js' => array(
            "/Scripting/jquery.externals/jquery.timers.js"
        ),
        '/Script/UI/Calendar/Main.js' => array(
            "/Script/UI/Dialogs.js",
            "/Scripting/jquery-ui.min.js"
        )
    );

    public function includes($includes)
    {
        if (is_string($includes)) $includes = array($includes);

        foreach ($includes as $include) {
            if (isset($this->_depends[$include])) {
                $this->_includes = $this->includes($this->_depends[$include]);
                array_push($this->_includes, $include);
            }
            else {
                array_push($this->_includes, $include);
            }
        }

        $this->_includes = array_unique($this->_includes);

        return $this->_includes;
    }
}
?>

4 个答案:

答案 0 :(得分:1)

  • 保留一个堆栈,最初是您的初始依赖关系(stack
  • 保留一个包含所有(传递)依赖项(deps
  • 的空数组
  • 虽然堆栈不是empty
    • pop最后一个元素(el
    • el添加到deps
    • 循环遍历el的依赖关系
      • 如果依赖项为in deps,则不执行任何操作
      • 否则,pushstack

答案 1 :(得分:0)

您正在寻找的功能称为展平。它需要一个递归列表并返回每个级别的所有元素。

在这里的评论中有一些PHP实现:http://php.net/manual/en/function.array-values.php

以下是javascript中的实现:http://tech.karbassi.com/2009/12/17/pure-javascript-flatten-array/

答案 2 :(得分:0)

试试这个:

function getDependentFiles($file, $dependencies) {
    $fileIndex = array();
    $queue = array($file);
    while (count($queue)) {
        $f = array_shift($queue);
        if (!isset($fileIndex[$f])) {
            if (array_key_exists($f, $dependencies) && is_array($dependencies[$f])) {
                $queue = array_merge($queue, $dependencies[$f]);
            }
            $fileIndex[$f] = true;
        }
    }
    return array_keys($fileIndex);
}
var_dump(getDependentFiles('/Script/UI/Calendar/Main.js', $_depends));

这基本上实现了Artefacto描述的算法。

答案 3 :(得分:0)

看看这是否有效 - 你的功能的一个小模块。

(顺便说一句,由于你的命名惯例,它是令人费解的:$ includes,$ include,$ this-&gt; _includes和$ this-&gt; includes()!!建议你使用更好的名字。我已经重命名了compute_includes的函数,但你也应该清理其他函数。)

public function calculate_includes($includes) {

        foreach ((array)$includes as $include) {

            if(in_array($include, $this->_includes)) continue;

            if (isset($this->_depends[$include])) {
                $this->_includes = $this->calculate_includes($this->_depends[$include]);
            } else {
                array_push($this->_includes, $include);
            }
        }

        $this->_includes = array_unique($this->_includes);

        return $this->_includes;
    }