문제

PHP 배열에는 요소에 대한 배열이있을 수 있습니다. 그리고 그 배열에는 배열 등이있을 수 있습니다. PHP 배열에 존재하는 최대 중첩을 찾는 방법이 있습니까? 예제는 초기 배열에 요소로 배열이없는 경우 1을 반환하는 함수, 2 이상 요소가 배열 인 경우 2 등을 반환합니다.

도움이 되었습니까?

해결책

이렇게해야합니다.

<?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;
}

?>

편집 : 매우 빨리 테스트했으며 작동하는 것으로 보입니다.

다른 팁

켄트 프레드릭이 지적한 문제를 피하는 또 다른 대안이 있습니다. 그것은 준다 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;
}

조심하십시오 그것을 재귀 적으로하는 예제.

PHP는 해당 배열의 다른 장소에 대한 참조로 배열을 만들 수 있으며 마찬가지로 재귀 참조가있는 개체를 포함 할 수 있으며, 그러한 경우에 순수한 재귀 알고리즘을 고려할 수 있습니다. 위험하게 순진한 것, 그것은 스택 깊이 재귀를 넘어서서 끝나지 않을 것이라는 점에서 결코 끝나지 않습니다.

(글쎄, 그것은 스택 깊이를 초과 할 때 종료 될 것이며, 그 시점에서 당신의 프로그램은 내가 원하는 것이 아니라 치명적으로 종료됩니다).

과거에는 Serialise-> 참조 마커를 문자열로 교체했습니다 -> 내 요구에 대한 Deserialise (종종 재귀 적 참조가 많은 뒷골목을 디버깅하는 것)가 잘 작동하는 것처럼 보이지만 어디서나 구멍을 뚫을 수 있지만 그 작업에 효과가 있습니다. .

작업을 위해 배열/구조가 재귀 참조가 자라는 것을 발견하면 여기에서 사용자가 기여한 댓글을 살펴볼 수 있습니다. http://php.net/manual/en/language.references.spot.php

그리고 어떻게 든 재귀 경로의 깊이를 계산하는 방법을 찾으십시오.

Algorhthms에 대한 CS 책을 꺼내서이 아기들을 때려야 할 수도 있습니다.

(너무 짧아서 죄송하지만 그래프 이론을 탐구하는 것은이 형식에 적합한 것 이상입니다;))))))))))))

안녕하세요 이것은 대체 솔루션입니다.

/*** 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;
}

여기서 약간의 영감을 얻은 후 그리고 이것을 찾은 후 재귀 인체 테이로 테이터 PHP 문서에서 나는이 솔루션에 왔습니다.

당신은 이것을 꽤 깔끔하게 사용해야합니다.

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;
}

PHP5와 PHP7 모두에서 작동합니다. 이것이 도움이되기를 바랍니다.

이 게시물을 발견했을 때이 질문에 대한 답변을 방금 해결했습니다. 여기 내 해결책이 있습니다. 나는 이것을 다양한 배열 크기로 시도하지 않았지만 ~ 30 피스 깊이> 4로 작업 한 데이터에 대한 2008 년 답변보다 빠릅니다.

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;
}

경고: 이것은 처리되지 않습니다 어느 가장자리 케이스. 강력한 솔루션이 필요한 경우 다른 곳에서 보이지만 간단한 경우에는 이것이 매우 빠른 것으로 나타났습니다.

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;
}

첨가 기본값 에게 $ childrenkey 어린이 요소에 대한 키가없는 간단한 배열에서 기능을 작동시킬 수 있습니다. 즉, 간단한 다차원 배열에 대해 작동합니다.

이 기능은 이제 다음을 사용하여 호출 할 수 있습니다.

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

또는

$my_array_depth = array_depth($my_array);

언제 $ my_array 자식 요소를 저장할 수있는 특정 키가 없습니다.

다음은 제레미 루텐의 기능의 약간 수정 된 버전입니다.

// 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;
}
}

같은 것들 print array_depth($GLOBALS) 재귀로 인해 오류가 발생하지 않지만 예상 한 결과를 얻지 못할 수도 있습니다.

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";

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

오래된 질문이지만이 날짜와 관련이 있습니다. :)

제레미 루텐 (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;
}

호출 된 두 번째 매개 변수를 추가했습니다 $ childrenkey 어린이 요소를 특정 키에 저장하기 때문입니다.

함수 호출의 예는 다음과 같습니다.

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

나는 내장 된 것이 없다고 생각합니다. 간단한 재귀 기능은 쉽게 찾을 수 있습니다.

// very simple and clean approach        
function array_depth($a) {
          static $depth = 0;
          if(!is_array($a)) {
            return $depth;
          }else{
            $depth++;
            array_map("array_depth", $a);
            return $depth;
          }
        }
print "depth:" . array_depth(array('k9' => 'dog')); // return 1

켄트 프레드릭 (Kent Frederic)이 강조한 문제가 중요하다고 생각합니다. Yjerem과 ASIM이 제안한 답변은이 문제에 취약합니다.

Yjerem이 다시 제안한 들여 쓰기에 의한 접근 방식은 Print_R 함수와의 들여 쓰기를 나타내는 공간의 수에 의존하기 때문에 나에게 충분히 안정적이지 않습니다. 시간/서버/플랫폼에 따라 다를 수 있습니다.

Joshn이 제안한 접근 방식은 정확할 수 있지만 내 것이 더 빠르다고 생각합니다.

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;
}

다른 방법을 비교하는 테스트를 수행하는 경우 메시지 게시. 제이

나는 당신이 '['및 ']'또는 ',', '및': '를 필터링하는 것을 잊어 버렸다고 생각합니다. 다음은 Array_Depth와 보너스 Array_SORT_BY_DEPTH의 업데이트입니다.

function array_depth($arr){
if (is_array($arr)) {
    array_walk($arr, 
        function($val, $key) use(&$arr) {
            if ((! is_string($val)) && (! is_array($val))) {
                $val = json_encode($val, JSON_FORCE_OBJECT);
            }

            if (is_string($val)) {
                $arr[$key] = preg_replace('/[:,]+/', '', $val);
            }
        }
    );

    $json_strings = explode(',', json_encode($arr, JSON_FORCE_OBJECT));

    $max_depth = 0;

    foreach ($json_strings as $json_string){
        var_dump($json_string); echo "<br/>";
        $json_string = preg_replace('/[^:]{1}/', '', $json_string);
        var_dump($json_string); echo "<br/><br/>";
        $depth = strlen($json_string);

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

            return $max_depth;
    }

    return FALSE;
    }


    function array_sort_by_depth(&$arr_val, $reverse = FALSE) {

  if ( is_array($arr_val)) { 
    $temp_arr = array();
            $result_arr = array();

            foreach ($arr_val as $key => $val) {
                $temp_arr[$key] = array_depth($val);
            }

        if (is_bool($reverse) && $reverse == TRUE) {
                arsort($temp_arr);
            }
            else {
                asort($temp_arr);
            }

            foreach ($temp_arr as $key => $val) {
                $result_arr[$key] = $arr_val[$key];
            }

            $arr_val = $result_arr;

    return TRUE;
     }

     return FALSE;
  }

코드를 자유롭게 개선하십시오 : D!

나는 이것이 재귀 문제를 해결하고 Serialize 또는 Print_r과 같은 다른 PHP 함수에 의존하지 않고 깊이를 줄 것이라고 생각합니다 (기껏해야 위험하고 다루기 어려운 버그로 이어질 수 있음).

function array_depth(&$array) {
    $max_depth = 1;
    $array['__compute_array_depth_flag_ZXCNADJHHDKAQP'] = 1;

    foreach ($array as $value) {
        if (is_array($value) &&
                    !isset($value['__compute_array_depth_flag_ZXCNADJHHDKAQP']))  {
            $depth = array_depth($value) + 1;

            if ($depth > $max_depth) {
                $max_depth = $depth;
            }
        }
    }
    unset($array['__compute_array_depth_flag_ZXCNADJHHDKAQP']);

    return $max_depth;
}

이것은 나에게 잘 작동하는 것 같습니다

<?php
function array_depth(array $array)
{
    $depth = 1;
    foreach ($array as $value) {
        if (is_array($value)) {
            $depth += array_depth($value);
            break;
        }
    }

    return $depth;
}

다음 코드를 사용합니다.

function maxDepth($array) {
    $iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array), \RecursiveIteratorIterator::CHILD_FIRST);
    $iterator->rewind();
    $maxDepth = 0;
    foreach ($iterator as $k => $v) {
        $depth = $iterator->getDepth();
        if ($depth > $maxDepth) {
            $maxDepth = $depth;
        }
    }
    return $maxDepth;
}

더 빠른 방법 :

max(array_map('count', $array));
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top