有没有办法在纯 PHP 中检测圆形数组? [英] Is there a way to detect circular arrays in pure PHP?

查看:22
本文介绍了有没有办法在纯 PHP 中检测圆形数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to implement my own serialization / var_dump style function in PHP. It seems impossible if there is the possibility of circular arrays (which there is).

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

In recent PHP versions, var_dump seems to detect circular arrays:

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

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

How would I implement my own serialization type of method in PHP that can detect similarly? I can't just keep track of which arrays I've visited, because strict comparison of arrays in PHP returns true for different arrays that contain the same elements and comparing circular arrays causes a Fatal Error, anyways.

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 值(为什么?).

I've looked for a way to find a unique id (pointer) for an array, but I can't find one. spl_object_hash only works on objects, not arrays. If I cast multiple different arrays to objects they all get the same spl_object_hash value (why?).

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

Calling print_r, var_dump, or serialize on each array and then using some mechanism to detect the presence of recursion as detected by those methods is an algorithmic complexity nightmare and will basically render any use too slow to be practical on large nested arrays.

接受的答案:

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

I accepted the answer below that was the first to suggest temporarily altering the an array to see if it is indeed the same as another array. That answers the "how do I compare two arrays for identity?" from which recursion detection is trivial.

推荐答案

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

The isRecursiveArray(array) method below detects circular/recursive arrays. It keeps track of which arrays have been visited by temporarily adding an element containing a known object reference to the end of the array.

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

If you want help writing the serialization method, please update your topic question and provide a sample serialization format in your question.

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 中检测圆形数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆