编程语言
首页 > 编程语言> > 如何在递归解析关联数组时检查PHP中的循环引用?

如何在递归解析关联数组时检查PHP中的循环引用?

作者:互联网

我用循环引用创建了这个数组:

$arr = array(1 => 'one', 2 => 'two');
$arr[3] = &$arr;

我有一个函数递归打印出数组中的值,但我真的无法解决创建循环引用检查的问题.你怎么能这样做?

我打印数组的当前函数复制如下.我没有包括我在进行循环引用检查时所做的各种尝试.它们主要围绕一种策略来维护已经为每个递归分支打印的$items项目.这是因为我仍然希望允许打印重复值,如果它是正在解析的当前数组的父节点,则不打印值.

我遇到的问题是如何在这个$seen变量中添加引用而不是数组副本.但如果有效,我会很高兴再次使用其他策略.

function HTMLStringify($arr)
{

    if(is_array($arr)){
        $html = '<ul>';
        foreach ($arr as $key => $value) {

            $html .= '<li>' . $key;

            if(is_array($value)){

                //Conspicuously missing is a circular reference check,
                //causing infinite recursion. After a few failed attempts
                //at checking for this (e.g. discovering that array_push doesn't take references)
                //I have left it for further study.
                //(After all, Javascript's JSON.stringify() doesn't check for circular references)
                //TODO: Check for circular references

                $html .= HTMLStringify($value, $seen);
            }
            elseif(is_numeric($value) || is_string($value) || is_null($value))
            {
                $html .= ' = ' . $value;
            }
            else
            {
                $html .= ' [couldn\'t parse ' . gettype($value) . ']';
            }

            $html .= '</li>';

        }
        $html .= '</ul>';
        return $html;
    }
    else
    {
        return null;
    }
}

解决方法:

使用the answer linked by Ryan Vincent中严格的in_array检查,您的代码的改编版本如下所示:

function HTMLStringify($arr, array $seen = array()) {
    if (is_array($arr)) {
        $seen[] = $arr;
        $html = '<ul>';

        foreach ($arr as $key => $value) {
            $html .= '<li>' . $key;

            if (is_array($value)) {

                if (in_array($value, $seen, true)) {
                    // Deal with recursion in your own way here
                    $html .= ' [RECURSION]';
                } else {
                    $html .= HTMLStringify($value, $seen);
                }

            } elseif (is_numeric($value) || is_string($value) || is_null($value)) {
                $html .= ' = ' . $value;
            } else {
                $html .= ' [couldn\'t parse ' . gettype($value) . ']';
            }

            $html .= '</li>'; 
        }

        return $html . '</ul>';
    } else {
        return null;
    }
}

$arr = array(1 => 'one', 2 => 'two');
$arr[3] = &$arr;
echo HTMLStringify($arr);

Comparing across a number of PHP versions,看起来这适用于PHP 5.3.15和PHP 5.4.5.

标签:php,arrays,recursion,circular-reference
来源: https://codeday.me/bug/20190708/1404836.html