有没有一种方法来检测纯PHP圆形阵列? [英] Is there a way to detect circular arrays in pure PHP?

查看:186
本文介绍了有没有一种方法来检测纯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数组的严格比较返回包含相同的元素,比较圆阵导致致命错误,反正不同的数组如此。

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或序列化每个阵列上,然后使用一些机制,通过这些方法作为检测来检测递归的presence是一个算法的复杂性的梦魇,将基本呈现任何使用过慢是大实用嵌套数组。

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(阵列)方法检测循环/递归阵列。它跟踪哪些阵列已经访问了暂时添加含有已知对象引用到阵列的端部的元素。

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天全站免登陆