Checking if array is multidimensional or not?

111,525

Solution 1

The short answer is no you can't do it without at least looping implicitly if the 'second dimension' could be anywhere. If it has to be in the first item, you'd just do

is_array($arr[0]);

But, the most efficient general way I could find is to use a foreach loop on the array, shortcircuiting whenever a hit is found (at least the implicit loop is better than the straight 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

Implicit looping, but we can't shortcircuit as soon as a match is found...

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

Solution 2

Use count() twice; one time in default mode and one time in recursive mode. If the values match, the array is not multidimensional, as a multidimensional array would have a higher recursive count.

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

This option second value mode was added in PHP 4.2.0. From the PHP Docs:

If the optional mode parameter is set to COUNT_RECURSIVE (or 1), count() will recursively count the array. This is particularly useful for counting all the elements of a multidimensional array. count() does not detect infinite recursion.

However this method does not detect array(array()).

Solution 3

For PHP 4.2.0 or newer:

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

Solution 4

I think this is the most straight forward way and it's state-of-the-art:

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

Solution 5

You can simply execute this:

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

If the optional mode parameter is set to COUNT_RECURSIVE (or 1), count() will recursively count the array. This is particularly useful for counting all the elements of a multidimensional array.

If it's the same, means there are no sublevels anywhere. Easy and fast!

Share:
111,525

Related videos on Youtube

Wilco
Author by

Wilco

Updated on July 02, 2020

Comments

  • Wilco
    Wilco almost 4 years
    1. What is the most efficient way to check if an array is a flat array of primitive values or if it is a multidimensional array?
    2. Is there any way to do this without actually looping through an array and running is_array() on each of its elements?
    • gahooa
      gahooa almost 14 years
      It's worth pointing out that PHP does not have true multi-dimensional arrays -- just simple associative array's of values. So your question is really asking "is there a non-scalar value in my array"?
    • Joe
      Joe almost 11 years
      Actually... I don't think that's worth pointing out at all.
  • Wilco
    Wilco over 15 years
    That's actually a good point. In my particular case, it's an either/or situation since I am controlling the creation of the original array. I'll leave the question open for now in case there's a solution that might work more generally though.
  • Vinko Vrsalovic
    Vinko Vrsalovic over 15 years
    This will only work for Greg's case. It's not a general solution to the problem where the second dimension could be anywhere in the array
  • Matthew Scharley
    Matthew Scharley over 15 years
    Good, with the caveat that I believe that your filtering line should have array_map("is_array",$a), not using is_array as a bareword.
  • Vinko Vrsalovic
    Vinko Vrsalovic over 15 years
    Good catch, that sped up is_multi, but still not good enough to match foreach
  • RoboTamer
    RoboTamer almost 13 years
    An array can not be detected on the key, you have to check the value
  • Tyzoid
    Tyzoid almost 11 years
    $arr = array("hello", "hi" => "hi there"); $arr[] = &arr; //oops
  • Jonas Äppelgran
    Jonas Äppelgran about 10 years
    Like this: if( is_array(current($arr)) ) { // is multidimensional }
  • Aistis
    Aistis over 9 years
    At least use if (isset($array[0])) { }. If you are sure the array's indexes start from 0
  • Mike Barwick
    Mike Barwick about 9 years
    Thanks...helpful. I wanted to check that a sub level to my array existed, I used if(count($tasks_by_date) !== count($tasks_by_date, 1))
  • Pian0_M4n
    Pian0_M4n about 9 years
    Cool. COUNT_RECURSIVE or 1 is same for count()
  • Mike Barwick
    Mike Barwick about 9 years
    Absolutely. I just like less clutter and the !== was used to see is sub level existed. For theories who might be looking for something similar...etc.
  • Mike Barwick
    Mike Barwick about 9 years
    What you had wasn't returning true for me...I needed to add the !==
  • CragMonkey
    CragMonkey about 8 years
    It is worth noting that, as written, multi_3 will only work on zero-based non-associative arrays with no gaps in the indices, meaning it won't correctly identify any of these examples as multi-dimensional.
  • CragMonkey
    CragMonkey about 8 years
    This only tests if the FIRST element is multi-dimensional.
  • CragMonkey
    CragMonkey about 8 years
    A multi-dimensional array is an array that contains one or more arrays. This only checks to see if it contains an element with a key of zero.
  • CragMonkey
    CragMonkey about 8 years
    A multi-dimensional array is an array that contains one or more arrays. This only checks to see if it contains an element with a key of zero.
  • CragMonkey
    CragMonkey about 8 years
    This technique only finds multidimensional arrays if the first element is an array.
  • Wallace Vizerra
    Wallace Vizerra over 7 years
    With empty array, has fails
  • Xorifelse
    Xorifelse over 7 years
    In function is_multi() optimize the code by doing return count($rv)>0
  • Fanis Hatzidakis
    Fanis Hatzidakis over 7 years
    Not working for array(array()) or array(array(), array()) either. Generally, if an inside array is empty then the recursive count will correctly add 0 for it, thus making it match the normal count.
  • Arthur
    Arthur over 7 years
    As noted this does not work for elements with empty arrays
  • Marcello Mönkemeyer
    Marcello Mönkemeyer about 7 years
    Be cautious with using array_shift(), as it removes the first element and also resets numeric keys! Better use current() if still itching for a one-liner.
  • Robert Pounder
    Robert Pounder over 6 years
    if you're going to one-line it at least do the whole thing; foreach($a as $v) is_array($v) ? return TRUE : return FALSE;
  • vanamerongen
    vanamerongen over 6 years
    That won't be reliable if you want to ensure that any other element isn't nested either.
  • Supun Praneeth
    Supun Praneeth over 5 years
    $arr[0] could not be and array but $arr[1] could be an array
  • Vitor Rodrigues
    Vitor Rodrigues over 5 years
    is_array(array_values($arr)[0]) as a workaround for customized keys.
  • Yassine Sedrani
    Yassine Sedrani over 4 years
    @RobertPounder or even foreach($a as $v) return is_array($v) ? true : false;
  • aProgger
    aProgger about 2 years
    You just check the first array element if it is an array. What if it is not but the 2nd element is an array? For example $array = ['0' => 0, '1' => ['0' => 1]]; This is a multidim array but your function says false.