Проверка, является ли массив многомерным или нет? - PullRequest
125 голосов
/ 28 сентября 2008
  1. Какой самый эффективный способ проверить, является ли массив плоским массивом примитивных значений или, если это многомерный массив ?
  2. Есть ли способ сделать это, фактически не проходя через массив и работает is_array() на каждом из его элементов?

Ответы [ 23 ]

179 голосов
/ 15 июня 2009

Используйте count () дважды; один раз в режиме по умолчанию и один раз в рекурсивном режиме. Если значения совпадают, массив является , а не многомерным, поскольку многомерный массив будет иметь более высокий рекурсивный счет.

if (count($array) == count($array, COUNT_RECURSIVE)) 
{
  echo 'array is not multidimensional';
}
else
{
  echo 'array is multidimensional';
}

Эта опция второго значения mode была добавлена ​​в PHP 4.2.0. Из PHP Документов :

Если для необязательного параметра mode установлено значение COUNT_RECURSIVE (или 1), count () будет рекурсивно считать массив. Это особенно полезно для подсчета всех элементов многомерного массива. count () не обнаруживает бесконечную рекурсию.

Однако этот метод не обнаруживает array(array()).

122 голосов
/ 28 сентября 2008

Короткий ответ: нет, вы не можете сделать это, по крайней мере, неявно, зацикливаясь, если «второе измерение» может быть где угодно. Если это должно быть в первом элементе, вы просто сделаете

is_array($arr[0]);

Но самый эффективный общий способ, который я мог найти, - это использовать цикл foreach в массиве, замыкая его при каждом попадании (по крайней мере, неявный цикл лучше, чем прямой for ()):

$ more multi.php
<?php

$a = array(1 => 'a',2 => 'b',3 => array(1,2,3));
$b = array(1 => 'a',2 => 'b');
$c = array(1 => 'a',2 => 'b','foo' => array(1,array(2)));

function is_multi($a) {
    $rv = array_filter($a,'is_array');
    if(count($rv)>0) return true;
    return false;
}

function is_multi2($a) {
    foreach ($a as $v) {
        if (is_array($v)) return true;
    }
    return false;
}

function is_multi3($a) {
    $c = count($a);
    for ($i=0;$i<$c;$i++) {
        if (is_array($a[$i])) return true;
    }
    return false;
}
$iters = 500000;
$time = microtime(true);
for ($i = 0; $i < $iters; $i++) {
    is_multi($a);
    is_multi($b);
    is_multi($c);
}
$end = microtime(true);
echo "is_multi  took ".($end-$time)." seconds in $iters times\n";

$time = microtime(true);
for ($i = 0; $i < $iters; $i++) {
    is_multi2($a);
    is_multi2($b);
    is_multi2($c);
}
$end = microtime(true);
echo "is_multi2 took ".($end-$time)." seconds in $iters times\n";
$time = microtime(true);
for ($i = 0; $i < $iters; $i++) {
    is_multi3($a);
    is_multi3($b);
    is_multi3($c);
}
$end = microtime(true);
echo "is_multi3 took ".($end-$time)." seconds in $iters times\n";
?>

$ php multi.php
is_multi  took 7.53565130424 seconds in 500000 times
is_multi2 took 4.56964588165 seconds in 500000 times
is_multi3 took 9.01706600189 seconds in 500000 times

Неявное зацикливание, но мы не можем замкнуть накоротко, как только совпадение найдено ...

$ more multi.php
<?php

$a = array(1 => 'a',2 => 'b',3 => array(1,2,3));
$b = array(1 => 'a',2 => 'b');

function is_multi($a) {
    $rv = array_filter($a,'is_array');
    if(count($rv)>0) return true;
    return false;
}

var_dump(is_multi($a));
var_dump(is_multi($b));
?>

$ php multi.php
bool(true)
bool(false)
28 голосов
/ 30 сентября 2008

Для PHP 4.2.0 или новее:

function is_multi($array) {
    return (count($array) != count($array, 1));
}
10 голосов
/ 10 мая 2016

Я думаю, что это самый простой и современный метод:

function is_multidimensional(array $array) {
    return count($array) !== count($array, COUNT_RECURSIVE);
}
9 голосов
/ 22 марта 2014

Вы можете просто выполнить это:

if (count($myarray) !== count($myarray, COUNT_RECURSIVE)) return true;
else return false;

Если дополнительный параметр режима установлен на COUNT_RECURSIVE (или 1), count () будет рекурсивно считать массив Это особенно полезно для подсчета всех элементов многомерного массива.

Если это то же самое, значит, нигде нет подуровней. Легко и быстро!

7 голосов
/ 28 сентября 2008

Вы можете посмотреть проверку is_array() на первом элементе, предполагая, что если первый элемент массива является массивом, то и остальные из них тоже.

4 голосов
/ 26 июля 2013

Все отличные ответы ... вот мои три строки, которые я всегда использую

function isMultiArray($a){
    foreach($a as $v) if(is_array($v)) return TRUE;
    return FALSE;
}
2 голосов
/ 10 июня 2011

Я думаю, вы обнаружите, что эта функция самая простая, эффективная и самая быстрая.

function isMultiArray($a){
    foreach($a as $v) if(is_array($v)) return TRUE;
    return FALSE;
}

Вы можете проверить это так:

$a = array(1 => 'a',2 => 'b',3 => array(1,2,3));
$b = array(1 => 'a',2 => 'b');

echo isMultiArray($a) ? 'is multi':'is not multi';
echo '<br />';
echo isMultiArray($b) ? 'is multi':'is not multi';
2 голосов
/ 28 сентября 2008

Эта функция вернет int число измерений массива (украдено у здесь ).

function countdim($array)
{
   if (is_array(reset($array))) 
     $return = countdim(reset($array)) + 1;
   else
     $return = 1;

   return $return;
}
1 голос
/ 25 февраля 2018

Не использовать COUNT_RECURSIVE

нажмите на этот сайт, чтобы узнать почему

используйте rsort, а затем используйте isset

function is_multi_array( $arr ) {
rsort( $arr );
return isset( $arr[0] ) && is_array( $arr[0] );
}
//Usage
var_dump( is_multi_array( $some_array ) );
...