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_*
函数或更改原始数组的情况下执行此操作?
答案 0 :(得分:1)
问题是PHP没有一种机制来告诉你两个变量是否引用相同的zval(表示实际保持数据的内部数据类型)。这排除了跟踪您已经遍历的变量的解决方案。
如果没有此功能或修改元素(pin方法),很遗憾无法检测除var_dump()
或print_r()
黑客之外的递归数据结构。