0

我有以下数组

Array
(
    [0] => Homework2 (1).java
    [test2] => Array
    (
    )
    [1] => space-art-hd-473771.jpg
    [2] => Homework2.java
    [3] => factura_oct_2013.pdf
    [test] => Array
    (
        [0] => Homework2 (1).java
        [1] => space-art-hd-473771.jpg
        [2] => Homework2.java
    )
    [test3] => Array
    (
        [0] => Homework2 (1).java
        [testintest] => Array
        (
            [0] => Homework2 (1).java
            [1] => space-art-hd-473771.jpg
            [2] => Homework2.java
        )
        [1] => space-art-hd-473771.jpg
        [2] => Homework2.java
    )
)

我正在尝试显示一个 HTML 嵌套列表。所以数组的每个子元素都应该是父 UL 中的一个新 UL。我试图让这个递归,但我只设法获得了很多我已经拥有的值。

function map2ul($file_map,$html="") {
    var_dump($file_map);
    print "<br>";
    if ($html == "") $html = '<ul>';
    else $html .= '<ul>';
    foreach ($file_map as $df) :
        if (is_array($df)) :
            $html .= $this->map2ul($df,$html);
        else :
            $html .= '<li>';
            $html .= $df;
            $html .= '</li>';
        endif;
    endforeach;
    $html .= '</ul>';
    return $html;
}

这是我尝试过的,但似乎 foreach 语句的重复次数超过了需要的次数。

有人可以指出错误,以便我更好地理解如何递归吗?

4

2 回答 2

2

错误在这几行:

if ($html == "") $html = '<ul>';
else $html .= '<ul>';

当您尝试递归调用此函数时,非空$html值会递归传递,导致内部循环粘合子文件夹内容。@AgreeOrNot 已经指出了一种解决方案。另一个是不要传递$html给递归调用的函数:

$html .= $this->map2ul($df);

但我认为你的方法引入了一些不必要的逻辑和处理。

通过分析数组我们可以得出一个重要的结论:如果数组值是一个数组,那么对应的键就是文件夹名称。在其他情况下,该值为文件名:

function map2ul($file_map) {
    $html = '<ul>';
    foreach ($file_map as $file_id_or_folder_name => $file_name_or_folder_content) {
        // if the element is a file
        if ( ! is_array($file_name_or_folder_content)) {
            $html .= '<li>' . $file_name_or_folder_content . '</li>';
        } else { // if the element is a folder
            $html .= '<li>/ ' . $file_id_or_folder_name . '</li>';
        }
    }
    $html .= '</ul>';
    return $html;
}

现在在必要的地方注入子文件夹内容就足够了,即文件夹:

function map2ul($file_map) {
    $html = '<ul>';
    foreach ($file_map as $file_id_or_folder_name => $file_name_or_folder_content) {
        // if the element is a file
        if ( ! is_array($file_name_or_folder_content)) {
            $html .= '<li>' . $file_name_or_folder_content . '</li>';
        } else { // if the element is a folder
            $html .= '<li>/ ' . $file_id_or_folder_name . '</li>';
            // injecting sub-folder's contents
            $html .= map2ul($file_name_or_folder_content);
        }
    }
    $html .= '</ul>';
    return $html;
}

编辑

如果我想让这段代码$html .= '<li>' . $file_name_or_folder_content . '</li>';附加 data-filepath 属性,这将是 parent_folder/file_name 路径,我需要做什么?

您必须将完整路径传递给函数。并且需要在函数调用时构造完整路径:

function map2ul($file_map, $path = '') {
    $path = $path . '/';
    $html = '<ul>';
    foreach ($file_map as $file_id_or_folder_name => $file_name_or_folder_content) {
        // if the element is a file
        if ( ! is_array($file_name_or_folder_content)) {
            $html .= '<li data-filepath="' . $path . $file_name_or_folder_content . '">' . $file_name_or_folder_content . '</li>';
        } else { // if the element is a folder
            $html .= '<li>/ ' . $file_id_or_folder_name . '</li>';
            $html .= map2ul($file_name_or_folder_content, $path . $file_id_or_folder_name);
        }
    }
    $html .= '</ul>';
    return $html;
}

尝试不使用第二个参数,例如map2ul($file_map)使用第二个参数,例如map2ul($file_map, 'c:/my_files').

于 2013-10-16T09:03:51.743 回答
2
$html .= $this->map2ul($df,$html);

它不应该是串联,因为递归调用是基于参数的$html——也就是说,串联已经在递归调用中完成。将其更改为:

$html = $this->map2ul($df,$html);
于 2013-10-16T02:14:45.533 回答