Перевірка, чи масив багатовимірний чи ні?


137
  1. Який найефективніший спосіб перевірити, чи масив є плоским масивом примітивних значень чи це багатовимірний масив ?
  2. Чи є спосіб це зробити, не перебираючи ретельно масив і не запускаючи is_array()кожен його елемент?

9
Варто зазначити, що PHP не має справжніх багатовимірних масивів - просто прості асоціативні масиви значень. Отже, ваше запитання справді задає питання "чи є у мого масиву непалярне значення"?
gahooa

21
Насправді ... Я не думаю, що це взагалі варто вказувати.
Джо

Відповіді:


135

Коротка відповідь - ні, ви не можете цього зробити, принаймні, чітко розмовляючи, якщо "другий вимір" може бути де завгодно. Якщо це має бути в першому пункті, ви просто зробите це

is_array($arr[0]);

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

$ 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)

3
Добре, з застереженням, що я вважаю, що у вашій лінії фільтрації має бути array_map ("is_array", $ a), не використовуючи is_array як головне слово.
Меттью Шарлі

Хороший улов, що прискорив is_multi, але все ще недостатньо хороший, щоб відповідати передбачуваним
Vinko Vrsalovic,

2
Варто зазначити, що, як написано, multi_3 буде працювати лише на не асоціативних масивах на основі нуля без пропусків в індексах, тобто не буде правильно ідентифікувати жоден із цих прикладів як багатовимірний.
Cragmonkey

У функції is_multi()оптимізуйте код, зробившиreturn count($rv)>0
Xorifelse

is_array (array_values ​​($ arr) [0]) як вирішення для спеціалізованих ключів.
Vitor Rodrigues

191

Використовуйте count () двічі; один раз у режимі за замовчуванням та один раз у рекурсивному режимі. Якщо значення збігаються, масив не є багатовимірним, оскільки багатовимірний масив мав би більший рекурсивний підрахунок.

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

Це значення другого параметра modeбуло додано в PHP 4.2.0. Від Документів PHP :

Якщо для параметра необов'язкового режиму встановлено значення COUNT_RECURSIVE (або 1), count () буде рекурсивно рахувати масив. Це особливо корисно для підрахунку всіх елементів багатовимірного масиву. count () не виявляє нескінченну рекурсію.

Однак цей метод не виявляє array(array()).


2
Як зазначалося, це не працює для елементів з порожніми масивами
Артур

30

Для PHP 4.2.0 або новішої версії:

function is_multi($array) {
    return (count($array) != count($array, 1));
}

Не працює для того array(array())чи array(array(), array())іншого. Як правило, якщо внутрішній масив порожній, тоді рекурсивний підрахунок буде правильно додати 0 для нього, таким чином, він зрівняється з нормальним підрахунком.
Фаніс Хатцідакіс

13

Я думаю, що це найбільш прямий шлях вперед, і це найсучасніший:

function is_multidimensional(array $array) {
    return count($array) !== count($array, COUNT_RECURSIVE);
}

9

Ви можете просто виконати це:

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

Якщо для параметра необов'язкового режиму встановлено значення COUNT_RECURSIVE(або 1), count () буде рекурсивно рахувати масив. Це особливо корисно для підрахунку всіх елементів багатовимірного масиву.

Якщо це те саме, значить, ніде немає підрівнів. Легко і швидко!


Дякую ... корисно. Я хотів перевірити, чи існує підрівень для мого масиву, я використовувавif(count($tasks_by_date) !== count($tasks_by_date, 1))
Майк Барвік

Класно. COUNT_RECURSIVE або 1 те ж саме для count ()
Pian0_M4n

Абсолютно. Мені просто подобається менше захаращення, і, як !==звикли бачити, існує підрівень. Для теорій, які можуть шукати щось подібне ... тощо.
Майк Барвік

Те, що ти не повертав для мене правдою ... Мені потрібно було додати!==
Майк Барвік

З порожнім масивом має збій
Wallace Maxters

7

Ви можете перевірити is_array()перший елемент, припускаючи, що якщо перший елемент масиву є масивом, то решта з них теж.


Це насправді хороший момент. У моєму конкретному випадку це або /, або ситуація, оскільки я контролюю створення вихідного масиву. Я поки залишаю це питання відкритим на випадок, якщо є рішення, яке, можливо, спрацює більш загально.
Вілько

5
if( is_array(current($arr)) ) { // is multidimensional }
Ось так

4

Усі чудові відповіді ... ось мої три рядки, якими я завжди користуюся

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

2

Ця функція поверне int кількість розмірів масиву (викрадене звідси ).

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

   return $return;
}

Це спрацює лише для справи Грега. Це не загальне рішення проблеми, коли другий вимір може бути в будь-якому місці масиву
Вінко Врсалович,

$ arr = array ("привіт", "привіт" => "привіт там"); $ arr [] = & arr; // oops
Тизоїд

2

Я думаю, ви побачите, що ця функція є найпростішим, найефективнішим та найшвидшим способом.

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

якщо ви збираєтесь в один рядок, принаймні зробіть все це; foreach($a as $v) is_array($v) ? return TRUE : return FALSE;
Роберт Пундер

@RobertPounder або навітьforeach($a as $v) return is_array($v) ? true : false;
Yassine Sedrani

2

Після PHP 7 ви можете просто зробити:

public function is_multi(array $array):bool
{
    return is_array($array[array_key_first($array)]);
}

1

Ви також можете зробити просту перевірку, як це:

$array = array('yo'=>'dream', 'mydear'=> array('anotherYo'=>'dream'));
$array1 = array('yo'=>'dream', 'mydear'=> 'not_array');

function is_multi_dimensional($array){
    $flag = 0;
    while(list($k,$value)=each($array)){
        if(is_array($value))
            $flag = 1;
    }
    return $flag;
}
echo is_multi_dimensional($array); // returns 1
echo is_multi_dimensional($array1); // returns 0

1

Спробуйте наступним чином

if (count($arrayList) != count($arrayList, COUNT_RECURSIVE)) 
{
  echo 'arrayList is multidimensional';

}else{

  echo 'arrayList is no multidimensional';
}

1

Навіть це працює

is_array(current($array));

Якщо false, це одномірний масив, якщо true - багатомірний масив.

Поточний дасть вам перший елемент масиву і перевірить, чи є перший елемент масивом чи ні функцією is_array .


Це не буде надійним, якщо ви хочете переконатися, що будь-який інший елемент також не вкладений.
vanamerongen

1

Не використовуйте 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 ) );

$ arr [0] не може бути і масив, але $ arr [1] може бути масивом
Supun Praneeth

1

У моєму випадку. Я застряг у різному дивному стані.
1-й випадок = array("data"=> "name");
2-й випадок = array("data"=> array("name"=>"username","fname"=>"fname"));
Але якщо dataзамість значення має масив, то функція sizeof () або count () не працює для цієї умови. Тоді я створюю власну функцію для перевірки.
Якщо перший індекс масиву має значення, то він повертає "тільки значення",
але якщо індекс має масив замість значення, то він повертає "має масив",
я використовую цей спосіб

 function is_multi($a) {
        foreach ($a as $v) {
          if (is_array($v)) 
          {
            return "has array";
            break;
          }
          break;
        }
        return 'only value';
    }

Особлива подяка Вінко Врсаловичу


0

Я думаю, що цей класний (реквізити до іншого користувача, якому я не знаю його імені користувача):

static public function isMulti($array)
{
    $result = array_unique(array_map("gettype",$array));

    return count($result) == 1 && array_shift($result) == "array";
}

0

Усі перераховані вище методи занадто складні для швидкого розгортання. Якщо масив рівний, тестуючи перший елемент, слід повернути примітив, наприклад, int, string тощо. Якщо він багатомірний, він повинен повернути масив. За розширенням ви можете використовувати цей один вкладиш швидко і акуратно.

echo is_array(array_shift($myArray));

якщо це повертає істину, масив є багатовимірним. Інакше він плоский. Зауважимо, дуже часто рідкісні масиви мають різні розміри, наприклад, якщо ви генеруєте дані з моделі, вона завжди матиме один і той же тип багатовимірної або плоскої структури, який можна пройти циклами. машинно виготовлені петлі Якщо це не так, то ви створили його власноруч, це означає, що ви знаєте, де все буде, і це просто працює без необхідності писати циклічний алгоритм введіть тут опис зображення


Цей прийом знаходить багатовимірні масиви лише тоді, коли перший елемент є масивом.
Cragmonkey

Будьте обережні з використанням array_shift(), оскільки він видаляє перший елемент, а також скидає цифрові клавіші! Краще використовувати, current()якщо все-таки свербіть для однолінійного.
Marcello Mönkemeyer

0

На додаток до попередніх відповідей та залежно від схеми масиву, який ви хочете перевірити:

function is_multi_array($array=[],$mode='every_key'){

    $result = false;

    if(is_array($array)){

        if($mode=='first_key_only'){

            if(is_array(array_shift($array))){

                $result = true;
            }
        }
        elseif($mode=='every_key'){

            $result = true;

            foreach($array as $key => $value){

                if(!is_array($value)){

                    $result = false;
                    break;
                }
            }
        }
        elseif($mode=='at_least_one_key'){

            if(count($array)!==count($array, COUNT_RECURSIVE)){

                $result = true; 
            }
        }
    }

    return $result;
}


0
$is_multi_array = array_reduce(array_keys($arr), function ($carry, $key) use ($arr) { return $carry && is_array($arr[$key]); }, true);

Ось приємний один лайнер. Він перебирає кожну клавішу, щоб перевірити, чи є значення цього ключа масивом. Це забезпечить правду


-1
if($array[0]){
//enter your code 
}

Принаймні використовувати if (isset($array[0])) { }. Якщо ви впевнені, що індекси масиву починаються від 0
Aistis

Багатовимірний масив - це масив, який містить один або більше масивів. Це лише перевіряє, чи містить він елемент з ключем нуля.
Cragmonkey

-1
if ( array_key_exists(0,$array) ) {

// multidimensional array

}  else {

// not a multidimensional array

}

* тільки для тих масивів з числовим індексом


Багатовимірний масив - це масив, який містить один або більше масивів. Це лише перевіряє, чи містить він елемент з ключем нуля.
Cragmonkey

-1

Нативна функція print_r повертає читабельну людиною рядок. Просто порахуйте екземпляри "масиву".

спробуйте ...

substr_count(print_r([...array...], true), 'Array') > 1;

$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)));
$d = array(array());
$e = array(1, array());
$f = array(array(), array());
$g = array("hello", "hi" => "hi there");
$h[] = $g;

var_dump(substr_count(print_r($a, true), 'Array') > 1);
...

//a: bool(true)
//b: bool(false)
//c: bool(true)
//d: bool(true)
//e: bool(true)
//f: bool(true)
//g: bool(false)
//h: bool(true)

У моєму вікні "is_multi зайняв 0,83681297302246 секунд у 500000 разів"

Люб’язно: Руах Хакодеш



-3
is_array($arr[key($arr)]); 

Без петель, простий і простий.

Також працює з асоційованими масивами не тільки числові масиви, які не могли містити 0 (як у попередньому прикладі, викине вам попередження, якщо масив не має 0.)


Масив не можна виявити на ключі, ви повинні перевірити значення
RoboTamer
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.