php 有没有办法找出PHP数组的“深度”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/262891/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 22:07:16  来源:igfitidea点击:

Is there a way to find out how "deep" a PHP array is?

phparraysassociative-array

提问by Thomas Owens

A PHP array can have arrays for its elements. And those arrays can have arrays and so on and so forth. Is there a way to find out the maximum nesting that exists in a PHP array? An example would be a function that returns 1 if the initial array does not have arrays as elements, 2 if at least one element is an array, and so on.

PHP 数组可以为其元素包含数组。这些数组可以有数组等等。有没有办法找出PHP数组中存在的最大嵌套?一个例子是一个函数,如果初始数组没有数组作为元素,则返回 1,如果至少有一个元素是数组,则返回 2,依此类推。

回答by Jeremy Ruten

Here's another alternative that avoids the problem Kent Fredric pointed out. It gives print_r()the task of checking for infinite recursion (which it does well) and uses the indentation in the output to find the depth of the array.

这是避免 Kent Fredric 指出的问题的另一种选择。它为print_r()提供检查无限递归的任务(它做得很好)并使用输出中的缩进来查找数组的深度。

function array_depth($array) {
    $max_indentation = 1;

    $array_str = print_r($array, true);
    $lines = explode("\n", $array_str);

    foreach ($lines as $line) {
        $indentation = (strlen($line) - strlen(ltrim($line))) / 4;

        if ($indentation > $max_indentation) {
            $max_indentation = $indentation;
        }
    }

    return ceil(($max_indentation - 1) / 2) + 1;
}

回答by Jeremy Ruten

This should do it:

这应该这样做:

<?php

function array_depth(array $array) {
    $max_depth = 1;

    foreach ($array as $value) {
        if (is_array($value)) {
            $depth = array_depth($value) + 1;

            if ($depth > $max_depth) {
                $max_depth = $depth;
            }
        }
    }

    return $max_depth;
}

?>

Edit: Tested it very quickly and it appears to work.

编辑:非常快速地测试它,它似乎工作。

回答by Kent Fredric

Bewareof the examples that just do it recursively.

当心只是递归执行的示例。

Php can create arrays with references to other places in that array, and can contain objects with likewise recursive referencing, and any purely recursive algorithm could be considered in such a case a DANGEROUSLYnaive one, in that it will overflow stack depth recursing, and never terminate.

Php 可以创建引用该数组中其他位置的数组,并且可以包含具有同样递归引用的对象,在这种情况下,任何纯递归算法都可以被认为是一种危险的幼稚算法,因为它会溢出堆栈深度递归,并且永远不会终止。

( well, it will terminate when it exceeds stack depth, and at that point your program will fatally terminate, not what I think you want )

(好吧,它会在超过堆栈深度时终止,届时您的程序将致命终止,而不是我认为您想要的)

In past, I have tried serialise -> replacing reference markers with strings -> deserialise for my needs, ( Often debugging backtraces with loads of recursive references in them ) which seems to work OK, you get holes everywhere, but it works for that task.

过去,我尝试过序列化 -> 用字符串替换引用标记 -> 根据我的需要反序列化,(经常调试带有大量递归引用的回溯)这似乎工作正常,到处都是漏洞,但它适用于该任务.

For your task, if you find your array/structure has recursive references cropping up in it, you may want to take a look at the user contributed comments here: http://php.net/manual/en/language.references.spot.php

对于您的任务,如果您发现您的数组/结构中出现了递归引用,您可能需要在此处查看用户贡献的评论:http: //php.net/manual/en/language.references.spot .php

and then somehow find a way to count the depth of a recursive path.

然后以某种方式找到一种计算递归路径深度的方法。

You may need to get out your CS books on algorhthms and hit up these babies:

你可能需要拿出你关于算法的 CS 书籍并找到这些宝贝:

( Sorry for being so brief, but delving into graph theory is a bit more than suited for this format ;) )

(抱歉这么简短,但深入研究图论有点不适合这种格式;))

回答by Erick Brise?o

Hi This is an alternative solution.

嗨,这是一种替代解决方案。

/*** IN mixed (any value),OUT (string)maxDepth ***/
/*** Retorna la profundidad maxima de un array ***/
function getArrayMaxDepth($input){
    if( ! canVarLoop($input) ) { return "0"; }
    $arrayiter = new RecursiveArrayIterator($input);
    $iteriter = new RecursiveIteratorIterator($arrayiter);
    foreach ($iteriter as $value) {
            //getDepth() start is 0, I use 0 for not iterable values
            $d = $iteriter->getDepth() + 1;
            $result[] = "$d";
    }
    return max( $result );
}
/*** IN mixed (any value),OUT (bool)true/false, CHECK if can be used by foreach ***/
/*** Revisa si puede ser iterado con foreach ***/
function canVarLoop($input) {
    return (is_array($input) || $input instanceof Traversable) ? true : false;
}

回答by TwystO

After taking a little bit of inspiration here and after finding this RecursiveIteratorIteratorthing in PHP Documentation, I came to this solution.

在这里获得了一些灵感并在 PHP 文档中找到了这个RecursiveIteratorIterator之后,我来到了这个解决方案。

You should use this one, pretty neat :

你应该使用这个,非常整洁:

function getArrayDepth($array) {
    $depth = 0;
    $iteIte = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));

    foreach ($iteIte as $ite) {
        $d = $iteIte->getDepth();
        $depth = $d > $depth ? $d : $depth;
    }

    return $depth;
}

Works on both PHP5 and PHP7, hope this helps.

适用于 PHP5 和 PHP7,希望这会有所帮助。

回答by fncomp

I had just worked out an answer to this question when I noticed this post. Here was my solution. I haven't tried this on a ton of different array sizes, but it was faster than the 2008 answer for the data I was working with ~30 pieces depth >4.

当我注意到这篇文章时,我刚刚找到了这个问题的答案。这是我的解决方案。我还没有在大量不同的数组大小上尝试过这个,但它比 2008 年我正在处理的数据的答案要快,大约 30 个深度> 4。

function deepness(array $arr){
    $exploded = explode(',', json_encode($arr, JSON_FORCE_OBJECT)."\n\n");
    $longest = 0;
    foreach($exploded as $row){
        $longest = (substr_count($row, ':')>$longest)?
            substr_count($row, ':'):$longest;
    }
    return $longest;
}

Warning: this doesn't handle anyedge cases. If you need a robust solution look elsewhere, but for the simple case I found this to be pretty fast.

警告:这不处理任何边缘情况。如果您需要一个强大的解决方案,请查看其他地方,但对于简单的情况,我发现这非常快。

回答by dave1010

Here's my slightly modified version of jeremy Ruten's function

这是我对 jeremy Ruten 函数稍加修改的版本

// you never know if a future version of PHP will have this in core
if (!function_exists('array_depth')) {
function array_depth($array) {
    // some functions that usually return an array occasionally return false
    if (!is_array($array)) {
        return 0;
    }

    $max_indentation = 1;
    // PHP_EOL in case we're running on Windows
    $lines = explode(PHP_EOL, print_r($array, true));

    foreach ($lines as $line) {
        $indentation = (strlen($line) - strlen(ltrim($line))) / 4;
        $max_indentation = max($max_indentation, $indentation);
    }
    return ceil(($max_indentation - 1) / 2) + 1;
}
}

Things like print array_depth($GLOBALS)won't error due to the recursion, but you may not get the result you expected.

像这样的事情print array_depth($GLOBALS)不会因为递归而出错,但你可能不会得到你期望的结果。

回答by Amir Syafrudin

Another (better) modification to the function from Jeremy Ruten:

Jeremy Ruten 对函数的另一个(更好的)修改:

function array_depth($array, $childrenkey = "_no_children_")
{
    if (!empty($array[$childrenkey]))
    {
        $array = $array[$childrenkey];
    }

    $max_depth = 1;

    foreach ($array as $value)
    {
        if (is_array($value))
        {
            $depth = array_depth($value, $childrenkey) + 1;

            if ($depth > $max_depth)
            {
                $max_depth = $depth;
            }
        }
    }

    return $max_depth;
}

Adding a default valueto $childrenkeyallows the function to work for simple array with no keys for child elements, i.e. it will work for simple multi-dimensional arrays.

默认值添加到$childrenkey允许该函数适用于没有子元素键的简单数组,即它适用于简单的多维数组。

This function can now be called using:

现在可以使用以下方法调用此函数:

$my_array_depth = array_depth($my_array, 'the_key_name_storing_child_elements');

or

或者

$my_array_depth = array_depth($my_array);

when $my_arraydoesn't have any specific key for storing its child elements.

$my_array没有任何用于存储其子元素的特定键时。

回答by Amir Syafrudin

An old question, yet remain relevant to this date. :)

一个老问题,但仍然与这个日期相关。:)

Might as well contribute a minor modification to the answer from Jeremy Ruten.

不妨对 Jeremy Ruten 的答案做一个小的修改。

function array_depth($array, $childrenkey)
{
    $max_depth = 1;

    if (!empty($array[$childrenkey]))
    {
        foreach ($array[$childrenkey] as $value)
        {
            if (is_array($value))
            {
                $depth = array_depth($value, $childrenkey) + 1;

                if ($depth > $max_depth)
                {
                    $max_depth = $depth;
                }
            }
        }
    }

    return $max_depth;
}

I added a second parameter called $childrenkeybecause I store the child elements in a specific key.

我添加了第二个名为$childrenkey 的参数,因为我将子元素存储在特定键中。

An example of the function call is:

函数调用的一个例子是:

$my_array_depth = array_depth($my_array, 'the_key_name_storing_child_elements');

回答by shachibista

function createDeepArray(){
    static $depth;
    $depth++;
    $a = array();
    if($depth <= 10000){
        $a[] = createDeepArray();
    }
    return $a;
}
$deepArray = createDeepArray();

function deepness(array $arr){
    $exploded = explode(',', json_encode($arr, JSON_FORCE_OBJECT)."\n\n");
    $longest = 0;
    foreach($exploded as $row){
    $longest = (substr_count($row, ':')>$longest)?
        substr_count($row, ':'):$longest;
    }
    return $longest;
}

function array_depth($arr)
{
    if (!is_array($arr)) { return 0; }
    $arr = json_encode($arr);

    $varsum = 0; $depth  = 0;
    for ($i=0;$i<strlen($arr);$i++)
    {
    $varsum += intval($arr[$i] == '[') - intval($arr[$i] == ']');
    if ($varsum > $depth) { $depth = $varsum; }
    }

    return $depth;
}

echo 'deepness():', "\n";

$start_time = microtime(TRUE);
$start_memory = memory_get_usage();
var_dump(deepness($deepArray));
$end_time = microtime(TRUE);
$end_memory = memory_get_usage();
echo 'Memory: ', ($end_memory - $start_memory), "\n";
echo 'Time: ', ($end_time - $start_time), "\n";

echo "\n";
echo 'array_depth():', "\n";

$start_time = microtime(TRUE);
$start_memory = memory_get_usage();
var_dump(array_depth($deepArray));
$end_time = microtime(TRUE);
$end_memory = memory_get_usage();
echo 'Memory: ', ($end_memory - $start_memory), "\n";
echo 'Time: ', ($end_time - $start_time), "\n";

The function proposed by Josh was definitely faster:

Josh 提出的函数肯定更快:

$ for i in `seq 1 10`; do php test.php; echo '-------------------------';done
deepness():
int(10000)
Memory: 164
Time: 0.0079939365386963

array_depth():
int(10001)
Memory: 0
Time: 0.043087005615234
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0076408386230469

array_depth():
int(10001)
Memory: 0
Time: 0.042832851409912
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0080249309539795

array_depth():
int(10001)
Memory: 0
Time: 0.042320966720581
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0076301097869873

array_depth():
int(10001)
Memory: 0
Time: 0.041887998580933
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0079131126403809

array_depth():
int(10001)
Memory: 0
Time: 0.04217004776001
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0078539848327637

array_depth():
int(10001)
Memory: 0
Time: 0.04179310798645
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0080208778381348

array_depth():
int(10001)
Memory: 0
Time: 0.04272198677063
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0077919960021973

array_depth():
int(10001)
Memory: 0
Time: 0.041619062423706
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0080950260162354

array_depth():
int(10001)
Memory: 0
Time: 0.042663097381592
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0076849460601807

array_depth():
int(10001)
Memory: 0
Time: 0.042278051376343