php foreach 多维数组递归不起作用?

标签 php recursion multidimensional-array foreach associative-array

我上一个问题的某种后续:for loop - move deeper on numeric key in multidimensional array

我有这个数组作为输入:

Array
(
  [0] => apl_struct Object
    (
      [funcname] => say
      [args] => Array
        (
          [0] => Array
            (
              [0] => apl_struct Object
                (
                  [funcname] => text
                  [args] => Array
                    (
                      [value] => hello
                    )
                )
            )
        )
    )
)

我现在有 2 个功能为我工作。 一个是仅用于获取关联数组中的下一个键/值的函数。 next()、prev() 等都不像索引数组那样为我工作:

function getnext($array, $key) {
  $keys = array_keys($array);

  if ((false !== ($p = array_search($key, $keys))) && ($p < count($keys) - 1)) {
    return array('key' => $keys[++$p], 'value' => $array[$keys[$p]]);
  } else {return false;}
}

下一个函数是我的执行器或构造器。他为我创建了一个半 xmlstruct。 我尝试添加递归来跳过数字键。它们显然是废话,可以跳过。

然后我想检查非数字键的所有值是否都是数组。 如果它是一个数组,它指示要遵循的参数,输出应如下所示:INPUT。

如果不是,它要么是函数名 (funcname),要么是我们的真实值,例如“hello”。

function arr2xml($array, $level = 1, $pos = 1) {
  $xml = '';

  foreach ($array as $key => $value) {
    if (is_object($value)) {$value = get_object_vars($value);}// convert object to array
      if (is_numeric($key)) {
        $xml .= arr2xml($value);
      } else {
        if (!is_array($value)) {
          switch ($key) {
            case 'funcname':
              $nextkey = getnext($array, $key);
              $xml .= str_repeat("\t", $level) . "<apl:$value>\n";
              $xml .= arr2xml($nextkey['value'], $level++);
              $xml .= str_repeat("\t", $level) . "</apl:$value>\n";
              break;
            case 'value':
              $xml .= str_repeat("\t", $level) . "\t$value\n";
              break;
          }
        } else {
            $xml .= str_repeat("\t", $level) . "<$key pos='$pos'>\n\t";
            $xml .= arr2xml($value, $level++, $pos++);
            $xml .= str_repeat("\t", $level) . "</$key>\n";
        }
      }
  }

return $xml;
}

但到目前为止我得到的是: 函数名称插入正确。 这是说和文字。 此外,在某些狂野的情况下,-tag 和值可以正确执行。

<apl:say>
<apl:text>
    hello
    </apl:text>
    <args pos='1'>
        hello
      </args>
    </apl:say>
    <args pos='1'>
    <apl:text>
    hello
    </apl:text>
    <args pos='1'>
        hello
      </args>
      </args>
</xml>

对我来说,递归似乎并没有真正起作用。我在这里错过了什么吗? 我尝试从之前提到的帖子中重建它。

我也想知道我在这里得到的多个输出。 标签似乎填写正确,但实际的排列对我来说相当困惑。

我期望输出如下所示:

<apl:say>
  <args pos='1'>
    <apl:text>
      <args pos='1'>
      hello
      </args>
    </apl:text>
  </args>
</apl:say>

提前致谢

最佳答案

TL;DR

它是(完全多余的函数)getnext() 以及 arr2xml() 如何递归的组合。我在这里提供了一个 arr2xml() 替换函数,它将执行您想要的操作,而不需要 getnext()

下面详细描述了您的代码中出现的问题以及我建议如何修复它。

function arr2xml($array, $level = 0, $pos = 1) {
  $xml = '';

  foreach ($array as $key => $value) {
    if (is_object($value)) {
      $value = get_object_vars($value);
    }
    if (is_numeric($key)) {
      $xml .= arr2xml($value, $level+1);
      continue;
    } else {
      if (!is_array($value)) {
        switch ($key) {
          case 'funcname':
            array_shift($array);
            $xml .= str_repeat("    ", $level) . "<apl:$value>\n";
            $xml .= arr2xml($array, $level+1);
            $xml .= str_repeat("    ", $level) . "</apl:$value>\n";
            return $xml;
          case 'value':
            $xml .= str_repeat("    ", $level) . "    $value\n";
            return $xml;
        }
      } else {
          $xml .= str_repeat("    ", $level) . "<$key pos='$pos'>\n    ";
          $xml .= arr2xml($value, $level+1, $pos+1);
          $xml .= str_repeat("    ", $level) . "</$key>\n";
          return $xml;
      }
    }
  }

  return $xml;
}

Here是一个 eval.in,显示了在您提供的相同数据结构上使用的这个新函数,或多或少地为您提供了所需的输出(空格可能不完全是您想要的,我将其作为练习留给您。)

您的代码出了什么问题

funcname'say' 时,条件 case 'funcname': 调用 getnext() $key 设置为 'funcname'$array 设置为:

array(2) {
  ["funcname"]=>
  string(3) "say"
  ["args"]=>
  array(1) {
    [0]=>
    array(1) {
      [0]=>
      object(apl_struct)#1 (2) {
        ["funcname"]=>
        string(4) "text"
        ["args"]=>
        array(1) {
          ["value"]=>
          string(5) "hello"
        }
      }
    }
  }
}

然后,您在该数组中找到 'funcname' ($p = array_search($key, $keys)) 并创建一个仅包含数组中的下一项:

return array('key' => $keys[++$p], 'value' => $array[$keys[$p]]);

结果是一个不再包含 'args' 键的数组:

array(2) {
  ["key"]=>
  string(4) "args"
  ["value"]=>
  array(1) {
    [0]=>
    array(1) {
      [0]=>
      object(apl_struct)#1 (2) {
        ["funcname"]=>
        string(4) "text"
        ["args"]=>
        array(1) {
          ["value"]=>
          string(5) "hello"
        }
      }
    }
  }
}

因此,您永远不会获得您想要的标签,因为数据结构已被 getnext() 破坏,以删除您希望找到的 key 来构建它。

可以通过提前从内部递归返回来解决重复值。现在,您正在递归,处理“内部”节点,然后返回到顶部并再次处理它们。

相反,我们可以完全删除 getnext (因为它甚至没有做你想要的事情),我们可以只使用 array_shift而不是丢弃数组最左边的值。然后我们继续像平常一样处理 $array

关于php foreach 多维数组递归不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26518573/

相关文章:

php - Laravel 5.1 - 在保存到数据库时生成唯一的 10 个字母数字字符代码

php - 将一个元素移动到数组的末尾

php - OneDrive 通过 php 上传

java - 检查该方法是否已使用该输入执行的方法

java - Java 双维数组

php - 如何从 WordPress 数据库中的 BLOB 列检索数值数据

javascript - 递归算法的空间复杂度是否一定至少与递归调用的深度一样大?

json - 用 Circe 递归替换所有 JSON 字符串值

java - String[][] 出现越界异常错误

javascript - 二维数组 Javascript