繁体   English   中英

用PHP从线性数组创建一个多维数组

[英]Create a multi-dimensional array with PHP from lineal array

TL;DR我正在寻找一个函数来从 PHP 中的一维数组创建嵌套的<ol>列表。

1)目前我的测试页面中有这个简化的标记:

<h2>Spiders</h2>
<h2>Beetles</h2>
<h3>External morphology</h3>
<h4>Head</h4>
<h4>Thorax</h4>
<h4>Legs</h4>
<h3>Anatomy and physiology</h3>
<h2>Ants</h2>

2)然后被一个非常简单的函数捕获到一个一维数组中,如下所示:

array
(
    0 => "H2 Spiders",
    1 => "H2 Beetles",
    2 => "H3 External morphology",
    3 => "H4 Head",
    4 => "H4 Thorax",
    5 => "H4 Legs",
    6 => "H3 Anatomy and physiology"
    7 => "H2 Ants"
);

3)这是棘手的部分,因为我使用下一个循环和这些过于复杂的 if 语句来填充多维数组。

$toc = array ();
//
foreach ($array as $value) {
    $value_arr = explode(' ', $value, 2);
    $depth = str_replace("H", "", $value_arr[0]);
    $content = $value_arr[1];
    //
    if ($depth == 1) $toc[$title] = null;
    elseif ($depth == 2) {
        if (empty (end ($toc))) $toc[array_key_last ($toc)] = array ($title => null);
        else $toc[array_key_last ($toc)][$title] = null;
    } elseif ($depth == 3) {
        if (empty (end ($toc[array_key_last ($toc)]))) $toc[array_key_last ($toc)][array_key_last ($toc[array_key_last ($toc)])] = array ($title => null);
        else $toc[array_key_last ($toc)][array_key_last ($toc[array_key_last ($toc)])][$title] = '';
    }
}

输出:

Array (
[Spiders] => 
[Beetles] => Array
    (
        [External morphology] => Array
            (
                [Head] => 
                [Thorax] => 
                [Legs] => 
            )
        [Anatomy and physiology] => 
    )
[Ants] => 
)

4)最后用这个函数解析成一个完美缩进的html列表。

function table_of_contents ($toc, $output = '') {
    foreach ($toc as $key => $value) {
        $output = "$output <li><a href='#@" . sanitize_title ($key) . "'>$key</a>" . (is_array ($value) ? table_of_contents ($value) : null) . '</li>';
    }
    //
    return "<ol>$output</ol>";
}
//
table_of_contents ($toc);

——

  1. 蜘蛛
  2. 甲虫
    1. 外部形态
      1. 胸部
    2. 解剖学和生理学
  3. 蚂蚁

在第 1、第 2 和第 4 步中一切正常,但我目前的方法有一个缺点,即在第 3 步中仅允许我从第一个数组获得最多三个级别的深度。

我的问题是是否有一种更有效、更简洁的方法来创建具有(也许)递归函数或类似函数的多维数组?

使用preg_match_all解析输入可能更容易; 这可以为您提供深度和相关值的数组。 然后你可以遍历这些数组,当深度增加时打开一个<ol> ,当深度减少时关闭它:

$html = '<h2>Spiders</h2>
<h2>Beetles</h2>
<h3>External morphology</h3>
<h4>Head</h4>
<h4>Thorax</h4>
<h4>Legs</h4>
<h3>Anatomy and physiology</h3>
<h2>Ants</h2>';

preg_match_all('/<h(\d)>([^<]+)/', $html, $matches);
$cdepth = $matches[1][0] - 1;
foreach ($matches[1] as $key => $depth) {
    if ($depth > $cdepth) {
        echo "\n" . str_repeat(' ', $cdepth * 4) . "<ol>\n";
    }
    elseif ($depth < $cdepth) {
        echo "</li>\n" . str_repeat(' ', $depth * 4) . "</ol>\n" . str_repeat(' ', $depth * 4) . "</li>\n";
    }
    else {
        echo "</li>\n";
    }
    $cdepth = $depth;
    echo str_repeat(' ', $cdepth * 4) . "<li><a href=\"{$matches[2][$key]}\">{$matches[2][$key]}</a>";
}
while ($cdepth-- >= $matches[1][0]) {
    echo "</li>\n" . str_repeat(' ', $cdepth * 4) . "</ol>\n";
}

输出:

 <ol> <li><a href="Spiders">Spiders</a></li> <li><a href="Beetles">Beetles</a> <ol> <li><a href="External morphology">External morphology</a> <ol> <li><a href="Head">Head</a></li> <li><a href="Thorax">Thorax</a></li> <li><a href="Legs">Legs</a></li> </ol> </li> <li><a href="Anatomy and physiology">Anatomy and physiology</a></li> </ol> </li> <li><a href="Ants">Ants</a></li> </ol>

3v4l.org 上的演示

更新

如果出于输出以外的其他原因想要第三阶段数组,则可以使用此递归函数生成它(仍然可以从preg_match_all的输出中使用):

$html = '<h2>Spiders</h2>
<h2>Beetles</h2>
<h3>External morphology</h3>
<h4>Head</h4>
<h4>Thorax</h4>
<h4>Legs</h4>
<h5>Feet</h5>
<h3>Anatomy and physiology</h3>
<h2>Ants</h2>';


function push_values(&$k, $depth, $content) {
    $output = array();
    $cdepth = $depth[$k];
    while ($k < count($depth)) {
        if ($depth[$k] == $cdepth) {
            $output[$content[$k]] = '';
            $k++;
        }
        elseif ($depth[$k] > $cdepth) {
            $output[$content[$k-1]] = push_values($k, $depth, $content);
        }
        else {
            return $output;
        }
    }
    return $output;
}

preg_match_all('/<h(\d)>([^<]+)/', $html, $matches);
$key = 0;
print_r(push_values($key, $matches[1], $matches[2]));

输出:

Array
(
    [Spiders] => 
    [Beetles] => Array
        (
            [External morphology] => Array
                (
                    [Head] => 
                    [Thorax] => 
                    [Legs] => Array
                        (
                            [Feet] => 
                        )    
                )    
            [Anatomy and physiology] => 
        )    
    [Ants] => 
)

3v4l.org 上的演示

最后,我建议对@Nick 发布的第一个代码进行小修,在下一个场景中导致不受欢迎的 HTML 输出,其中大于 2 的深度差异将改变最肤浅的兄弟姐妹; 例如, <h6> <h3>之后的<h3>变成了<h5>而下一个<h2>被解析为<h4>

$html = '<h2>Spiders</h2>
<h2>Beetles</h2>
<h3>External morphology</h3>
<h4>Head</h4>
<h4>Thorax</h4>
<h4>Legs</h4>
<h5>Feet</h5>
<h6>Toes</h6>
<h3>Anatomy and physiology</h3>
<h2>Ants</h2>';

foreach ($matches[1] as $key => $depth) {
    if ($depth > $cdepth) {
        echo "\n" . str_repeat(' ', $cdepth * 4) . "<ol>\n";
    }
    elseif ($depth < $cdepth) {
        echo "</li>\n" . str_repeat(' ', $depth * 4) . "</ol>\n" . str_repeat(' ', $depth * 4) . "</li>\n";
    }
    else {
        echo "</li>\n";
    }
    $cdepth = $depth;
    echo str_repeat(' ', $cdepth * 4) . "<li><a href=\"{$matches[2][$key]}\">{$matches[2][$key]}</a>";
}
while ($cdepth-- >= $matches[1][0]) {
    echo "</li>\n" . str_repeat(' ', $cdepth * 4) . "</ol>\n";
}

输出:

 <ol> <li><a href="Spiders">Spiders</a></li> <li><a href="Beetles">Beetles</a> <ol> <li><a href="External morphology">External morphology</a> <ol> <li><a href="Head">Head</a></li> <li><a href="Thorax">Thorax</a></li> <li><a href="Legs">Legs</a> <ol> <li><a href="Feet">Feet</a> <ol> <li><a href="Toes">Toes</a></li> </ol> </li> <li><a href="Anatomy and physiology">Anatomy and physiology</a></li> </ol> </li> <li><a href="Ants">Ants</a></li> </ol> </li></ol></li></ol>

——

为了解决这个问题,我在添加下一个<li>元素之前添加了另一个while语句来放置正确数量的</li></ol> ,现在可以正确验证 W3C 检查器。

foreach ($matches[1] as $key => $depth) {
    if ($depth > $cdepth) {
        echo "\n" . str_repeat(' ', $cdepth * 4) . "<ol>\n";
    }
    elseif ($depth < $cdepth) {
        while ($cdepth -- > $depth) {
            echo "</li>\n" . str_repeat(' ', $depth * 4) . "</ol>\n" . str_repeat(' ', $depth * 4) . "\n";
        }
    }
    else {
        echo "</li>\n";
    }
    $cdepth = $depth;
    echo str_repeat(' ', $cdepth * 4) . "<li><a href=\"{$matches[2][$key]}\">{$matches[2][$key]}</a>";
}
while ($cdepth-- >= $matches[1][0]) {
    echo "</li>\n" . str_repeat(' ', $cdepth * 4) . "</ol>\n";
}

输出:

 <ol> <li><a href="Spiders">Spiders</a></li> <li><a href="Beetles">Beetles</a> <ol> <li><a href="External morphology">External morphology</a> <ol> <li><a href="Head">Head</a></li> <li><a href="Thorax">Thorax</a></li> <li><a href="Legs">Legs</a> <ol> <li><a href="Feet">Feet</a> <ol> <li><a href="Toes">Toes</a></li> </ol> </li> </ol> </li> </ol> <li><a href="Anatomy and physiology">Anatomy and physiology</a></li> </ol> <li><a href="Ants">Ants</a></li> </ol>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM