我遇到了一堆foreach循环,并且想知道是否有办法将它们简化为简单的'for'循环或递归函数?我正在尝试使用嵌套在彼此内部的元素生成HTML。我想我想要的是一个数组数组。但我不知道如何推进到目前为止我所创造的内容。 有人可以帮助我让这个怪物变得更加强大吗?谢谢!
这是我的代码:
$containers = DISPLAY::displayParentElements($data);
$subcontainers = DISPLAY::displayChildElements($data2);
foreach($containers as $parent) {
$parentDiv = $parent['parentDiv'];
echo '<div id="'.$parentDiv.'">';
foreach($subcontainers as $child) {
echo '<div id="'.$child['childDiv'].'">';
foreach($subcontainers as $grandChild) {
echo '<div id="'.$grandChild['grandChildDiv'].'">';
foreach($subcontainers as $greatGrandChild) {
echo '<div id="'.$greatGrandChild['greatGrandChildDiv'].'">';
echo '</div>';
}
echo '</div>';
}
echo '</div>';
}
echo '</div>';
}
结果将如下所示:
<div id="siteContainer">
<div id="header">
<div id="logoContainer">/div>
<div id="logo"></div>
<div id="links"></div>
<div id="contactInfo">
<div id="logoText">
<div id="shortDiv">
<div class="headerText"></div>
</div>
</div>
</div>
</div>
<div id="body">
<div id="longDiv"></div>
<div id="greetings"></div>
</div>
<div>
$containers
数组具有以下信息:
Array
(
[attribute_value] => siteContainer
)
Array
(
[attribute_value] => header
)
Array
(
[attribute_value] => logoContainer
)
Array
(
[attribute_value] => logo
)
Array
(
[attribute_value] => logoText
)
Array
(
[attribute_value] => links
)
Array
(
[attribute_value] => contactInfo
)
Array
(
[attribute_value] => body
)
Array
(
[attribute_value] => longDiv
)
Array
(
[attribute_value] => shortDiv
)
Array
(
[attribute_value] => headerText
)
Array
(
[attribute_value] => greetings
)
$subcontainers
数组具有几乎相同的信息,但有一个额外的键:
Array
(
[parent_container_name] => siteContainer
[attribute_value] => header
)
Array
(
[parent_container_name] => header
[attribute_value] => logoContainer
)
Array
(
[parent_container_name] => header
[attribute_value] => logo
)
Array
(
[parent_container_name] => contactInfo
[attribute_value] => logoText
)
Array
(
[parent_container_name] => header
[attribute_value] => links
)
Array
(
[parent_container_name] => header
[attribute_value] => contactInfo
)
Array
(
[parent_container_name] => siteContainer
[attribute_value] => body
)
Array
(
[parent_container_name] => body
[attribute_value] => longDiv
)
Array
(
[parent_container_name] => logoText
[attribute_value] => shortDiv
)
Array
(
[parent_container_name] => shortDiv
[attribute_value] => headerText
)
Array
(
[parent_container_name] => body
[attribute_value] => greetings
)
我很确定这两个数组可以缩小为一个,或仅使用$containers
数组。
答案 0 :(得分:1)
我不能从你的帖子中说出来,但是你发布的代码是你拥有的代码,你发布的输出是你想要的输出吗?您发布的代码...我想说不会,但实际上我不知道php足够确定...不应该产生您发布的输出。事实上,如果它产生任何输出,我会感到震惊。您发布的数组具有键值对。没有任何键是'parentDiv','childDiv','grandChildDiv'或'greatGrandChildDiv'。相反,它们只是第一个'attribute_value',第二个'attribute_value'和第二个'parent_container_name'。
为了生成您想要的输出,请尝试以下几行:
$containerWasGenerated = new array();
echo '<div id="siteContainer">';
$containerWasGenerated['siteContainer'] = true;
foreach($containers as $container) {
if($containerWasGenerated[$container['attribute_value'] != true) {
generateSubcontainers($container, $containers, $subcontainers, $containerWasGenerated);
$containerWasGenerated[$container['attribute_value']] = true;
}
}
echo '</div>';
function generateSubcontainers($parent, $containers, $subcontainers, $containerWasGenerated) {
echo '<div id="'.$parent['attribute_value'].'">';
foreach($containers as $subcontainer) {
if(getParent($subcontainer, $subcontainers) == $parent['attribute_value']) {
generateContainer($subcontainer, $containers, $subcontainers, $containerWasGenerated);
$containerWasGenerated[$subcontainer['attribute_value']] = true;
}
}
echo '</div>';
}
function getParent($container, $subcontainers) {
foreach($subconainters as $subcontainer) {
if($subcontainer['attribute_value'] == $container['attribute_value']) {
return $subcontainer['parent_container_name'];
}
}
}
免责声明:此代码未经测试,我的php有点生疏,所以它可能是多病的。但它应该是正确的方向。而且,它仍然非常低效。加速它的一种方法:保持子容器数组按parent_container_name排序,并编写一个更好的getParent()函数(例如使用二进制搜索)。希望这会有所帮助。
答案 1 :(得分:0)
这仅使用子容器和绝对父容器的名称。
function printChildren($parent, $children) {
echo '<div id="'.$parent.'">'."\n";
foreach($children as $child) {
if($child[0] == $parent) {
printChildren($child[1], $children);
}
}
echo '</div>'."\n";
}
printChildren('siteContainer', $subcontainers);
注意:这不会很好地标记代码......
答案 2 :(得分:0)
您应该为$ container中的节点指定一个空值为parent_container_name
的节点。这个
将代表顶级菜单节点。
接下来,使用array_merge
将两个阵列粘合在一起。
现在您有一个具有公共节点结构的数组,您可以轻松向下递归,呈现与当前节点匹配的 parent_container_name
的子元素,并以递归方式重复。
我想你想要这样的东西:
$menuNodes; // The array of all nodes
function RenderMenu()
{
// Grab all top-level nodes (nodes with no parent_container_name attribute)
$topLevelNodes = array();
foreach ($menuNodes as $node)
if ($node["parent_container_name"] == null)
$topLevelNodes[] = $node;
foreach ($topLevelNodes as $node)
RenderMenuNode($node);
}
function RenderMenuNode($node)
{
print "<div id='" . $node["attribute_value"] ."'>";
$node["isRendered"] = true;
// This filtering callback will discard elements that are not children or have already been rendered.
function Filter($element)
{
global $node;
return (!$element["isRendered"] && $element["parent_container_name"] == $node["parent_container_name]"]);
}
$children = array_filter($menuNodes, 'Filter');
foreach ($children as $child)
RenderMenuNode($child);
print "</div>";
}
我没有运行或测试过这段代码,它肯定会更有效率,但希望它能指出你正确的方向。理想情况下,您将从menuNodes数组中删除呈现的节点,这样您就不会不必要地重复迭代节点。
通过以这种方式递归地定义菜单结构,您可以根据需要嵌套菜单,而无需更改代码。希望这有帮助!
答案 3 :(得分:0)
执行此操作的最佳方法是使您的数组更像您想要表示的数据。因此,您将使键值对更加相关。我会创建以下数组:
$new_array = array(
[siteContainer] => array(
[header] => array(
[0] => "logo",
[1] => "links",
[contactInfo"] => array (
[0] => "logoInfo",
....
)
)
)
);
要在递归函数中执行以下操作,您需要编写:
function makeSubDiv($array)
{
foreach($array as $key=>$value)
{
if(is_array($value))
{
echo '<div id="'.$key.'">';
makeSubDiv($value);
echo '</div>';
}
else
{
echo '<div id="'.$value.'"></div>';
}
}
}
最后要合并你目前拥有的数组,我会有类似的东西。
// not sure why you have $containers because the data seems to be in subcontainers
$containers = DISPLAY::displayParentElements($data);
$subcontainers = DISPLAY::displayChildElements($data2);
function mergeToNested($subcontainers)
{
$return = array();
foreach($containers as $values)
{
$key = $values["parent_container_name";
if(isset($return[$key]))
{
if(is_array($return[$key]))
{
array_merge($return[$key], mergeToNested($return[$key]));
}
else
{
$return[$key] = array($values["attribute_value"]);
}
}
else if($index = array_search($key, $return) !== false)
{
unset($return[$index]);
$return[$key] = array();
}
else
{
$return[] = $key;
}
}
return $return;
}
Argh,希望您可以嵌套$ container和$ subcontainers,而无需通过mergeToNested()
函数推送它们。
注意强>:
此代码(尤其是MergeToNested函数)未经过测试,它是如何获取所需数据的想法,它可能无法按预期合并到所有嵌套级别。 ...随时测试和编辑任何更改。
答案 4 :(得分:0)
我对我的回答做了很多改动,我认为最好把它换成新的而不是编辑。
这次我包括我正在使用的输入数组,以防我错误解释你的开头。我还创建了一个函数来查找所有绝对父母,即没有父母的父母。
// list of subcontainers and their parents
$subcontainers = array(
array('siteContainer', 'header'), array('header', 'logoContainer'),
array('header', 'logo'), array('contactInfo', 'logoText'),
array('header', 'links'), array('header', 'contactInfo'),
array('siteContainer', 'body'), array('body', 'longDiv'),
array('logoText', 'shortDiv'), array('shortDiv', 'headerText'),
array('body', 'greetings'));
// recursively prints each container
function printChildren($parent, $children) {
echo '<div id="'.$parent.'">'."\n";
foreach($children as $child) {
if($child[0] == $parent) {
printChildren($child[1], $children);
}
}
echo '</div>'."\n";
}
// finds all parents that have no parents
function findAbsParent($subcontainers) {
$absParents = array();
foreach($subcontainers as $parent) {
$isAbs = true;
foreach($subcontainers as $child) {
if($parent[0] == $child[1]) {
$isAbs = false;
}
}
if($isAbs) {$absParents[] = $parent[0];}
}
return array_unique($absParents);
}
$absparents = findAbsParent($subcontainers);
// this is only needed if it's possible to have more then one absolute parent
if(is_array($absparents)) {
foreach($absparents as $absparent) {printChildren($absparent, $subcontainers);}
} else {
printChildren($absparents, $subcontainers);
}