php - 有没有办法在纯 PHP 中检测循环数组?

标签 php arrays recursion identity circular-reference

我正在尝试在 PHP 中实现我自己的序列化/var_dump 样式函数。如果有循环数组的可能性(确实存在),这似乎是不可能的。

在最近的 PHP 版本中,var_dump 似乎可以检测到循环数组:

php > $a = array();
php > $a[] = &$a;
php > var_dump($a);
array(1) {
  [0]=>
  &array(1) {
    [0]=>
    *RECURSION*
  }
}

我将如何在 PHP 中实现我自己的序列化类型的方法来进行类似的检测?我不能只跟踪我访问过的数组,因为 PHP 中数组的严格比较对于包含相同元素的不同数组返回 true,并且比较循环数组会导致 fatal error ,无论如何。

php > $b = array(1,2);
php > $c = array(1,2);
php > var_dump($b === $c);
bool(true)
php > $a = array();
php > $a[] = &$a;
php > var_dump($a === $a);
PHP Fatal error:  Nesting level too deep - recursive dependency? in php shell code on line 1

我一直在寻找一种方法来查找数组的唯一 ID(指针),但我找不到。 spl_object_hash 仅适用于对象,不适用于数组。如果我将多个 不同 数组转换为对象,它们都会得到相同的 spl_object_hash 值(为什么?)。

编辑:

在每个数组上调用 print_r、var_dump 或序列化,然后使用某种机制来检测这些方法检测到的递归的存在是算法复杂性的噩梦,并且基本上会使任何使用都太慢而无法在大型嵌套数组上实用。

接受的答案:

我接受了下面的答案,这是第一个建议临时更改一个数组以查看它是否确实与另一个数组相同的答案。这回答了“我如何比较两个数组的身份?”从中递归检测是微不足道的。

最佳答案

下面的 isRecursiveArray(array) 方法检测循环/递归数组。它通过在数组末尾临时添加一个包含已知对象引用的元素来跟踪访问了哪些数组。

如果您需要帮助编写序列化方法,请更新您的主题问题并在您的问题中提供示例序列化格式。

function removeLastElementIfSame(array & $array, $reference) {
    if(end($array) === $reference) {
        unset($array[key($array)]);
    }
}

function isRecursiveArrayIteration(array & $array, $reference) {
    $last_element   = end($array);
    if($reference === $last_element) {
        return true;
    }
    $array[]    = $reference;

    foreach($array as &$element) {
        if(is_array($element)) {
            if(isRecursiveArrayIteration($element, $reference)) {
                removeLastElementIfSame($array, $reference);
                return true;
            }
        }
    }

    removeLastElementIfSame($array, $reference);

    return false;
}

function isRecursiveArray(array $array) {
    $some_reference = new stdclass();
    return isRecursiveArrayIteration($array, $some_reference);
}



$array      = array('a','b','c');
var_dump(isRecursiveArray($array));
print_r($array);



$array      = array('a','b','c');
$array[]    = $array;
var_dump(isRecursiveArray($array));
print_r($array);



$array      = array('a','b','c');
$array[]    = &$array;
var_dump(isRecursiveArray($array));
print_r($array);



$array      = array('a','b','c');
$array[]    = &$array;
$array      = array($array);
var_dump(isRecursiveArray($array));
print_r($array);

关于php - 有没有办法在纯 PHP 中检测循环数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9105816/

相关文章:

php - 使用 javascript 渲染 DIV

php - 如何将两个 PDO 语句组合起来插入数据库?

java - 我怎样才能使这段代码最终打印一条语句来告诉是否至少有一个匹配项或文件不存在?

linux - 了解 NASM 程序集中的递归阶乘函数

php - Azure 租赁 Blob API 403 错误

php - 当键未知时如何找到关联数组的第一个/第二个元素?

PHP动态用户配置文件url

c - 将 char 数组传递给函数

java - 在 java 中查找整数数组中的模式长度?

javascript - 当我们需要返回一个值时,为什么我们在递归中需要 "return"?