在PHP中确定无限嵌套数组

时间:2013-08-26 09:21:49

标签: php arrays recursion

SO,

我在PHP中确定数组递归时遇到问题。假设我有一个动态生成的数组,最终看起来像:

$rgData = [
   ['foo', 'bar', $rgTemp=[7, 31, true]],
   [-5, &$rgData, 'baz']
];

(这里的变量链接是动态提供的,可能指的是数组本身)。另一个样本:

$rgData = [
   ['foo', 'bar', $rgTemp=[7, 31, true]],
   [-5, &$rgTemp, 'baz']
]; 

两个数组内部都有一些引用,但第二个看起来很好,因为它的引用没有循环。后来,由于我的逻辑,我必须通过递归函数处理数组(类似array_walk_recursive) - 并且,由于无限嵌套数组递归,因此我得到致命错误上面的第一个样本。

我的问题是 - 如何确定数组是否具有无限递归。请注意,这个问题比从数组内部到自身的简单搜索链接更复杂,因为我们可以使用类似的东西:

$rgOne = [
   ['foo', 'bar'],
   ['baz']
];
$rgTwo = [6, 'test', &$rgOne];
$rgOne[1][] = &$rgTwo;

即。更复杂的递归。我发现PHP可以在var_dump和类似函数中以某种方式解决这个问题 - 例如,第三个示例的转储将如下所示:

array(2) {
  [0]=>
  array(2) {
    [0]=>
    string(3) "foo"
    [1]=>
    string(3) "bar"
  }
  [1]=>
  array(2) {
    [0]=>
    string(3) "baz"
    [1]=>
    &array(3) {
      [0]=>
      int(6)
      [1]=>
      string(4) "test"
      [2]=>
      &array(2) {
        [0]=>
        array(2) {
          [0]=>
          string(3) "foo"
          [1]=>
          string(3) "bar"
        }
        [1]=>
        *RECURSION*
      }
    }
  }
}

即。 * RECURSION * 被抓住了。目前,我试图通过功能来解决问题:

function isLooped(&$rgData, &$rgCurrent=null)
{
   foreach($rgData as $mKey=>$mValue)
   {
      if(is_array($mValue) && isset($rgCurrent) && 
         $rgCurrent===$rgData /* that's where, it seems, I need help*/)
      {
         return true;
      }
      elseif(is_array($mValue) && isLooped($mValue, $rgData))
      {
         return true;
      }
   }
   return false;
}

但没有成功(我知道为什么 - 这种比较无效)。我现在唯一的想法是做一些奇怪的事情,比如:

function isLooped(&$rgData)
{
   $rgTemp  = @var_export($rgData, 1);
   return preg_match('/circular references/i', error_get_last()['message']);
}

但这很可悲,因为我至少需要将我的数组数据复制到一些临时存储器中(此外,所有这些看起来都是一个小故障,而不是一个合适的解决方案)。那么,可能有一些关于如何以正常方式做的想法?

更新:通过更改数组中的键,然后在递归循环中查找它,我发现 solution。这比var_*函数要好得多,但仍然不是我想要的。有没有办法在没有var_*函数或更改原始数组的情况下执行此操作?

1 个答案:

答案 0 :(得分:1)

问题是PHP没有一种机制来告诉你两个变量是否引用相同的zval(表示实际保持数据的内部数据类型)。这排除了跟踪您已经遍历的变量的解决方案。

如果没有此功能或修改元素(pin方法),很遗憾无法检测除var_dump()print_r()黑客之外的递归数据结构。