1

所以,

我在确定 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类似的函数中以某种方式解决这个问题 - 例如,第三个示例的转储将如下所示:

数组(2){
  [0]=>
  数组(2){
    [0]=>
    字符串(3)“富”
    [1]=>
    字符串(3)“酒吧”
  }
  [1]=>
  数组(2){
    [0]=>
    字符串(3)“巴兹”
    [1]=>
    &array(3) {
      [0]=>
      整数(6)
      [1]=>
      字符串(4)“测试”
      [2]=>
      &数组(2){
        [0]=>
        数组(2){
          [0]=>
          字符串(3)“富”
          [1]=>
          字符串(3)“酒吧”
        }
        [1]=>
        *递归*
      }
    }
  }
}

*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']);
}

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

更新:通过更改数组中的键然后在递归循环中查找它找到了解决方案。这比函数要好得多var_*,但仍然不是我想要的。有没有办法在没有var_*函数或更改原始数组的情况下做到这一点?

4

1 回答 1

1

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

如果没有此功能或修改元素(pin 方法),遗憾的是无法检测到递归数据结构,除非是var_dump()print_r()hack。

于 2013-08-26T11:08:19.070 回答