tags:

views:

1817

answers:

6

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? Is there any way to do this without actually looping through an array and running is_array() on each of its elements?

+1  A: 

You could look check is_array() on the first element, under the assumption that if the first element of an array is an array, then the rest of them are too.

Greg Hewgill
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.
Wilco
+1  A: 

This function will return int number of array dimensions (stolen from here).

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

   return $return;
}
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
Vinko Vrsalovic
+10  A: 

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)
Vinko Vrsalovic
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.
Matthew Scharley
Good catch, that sped up is_multi, but still not good enough to match foreach
Vinko Vrsalovic
+7  A: 

For PHP 4.2.0 or newer:

function is_multi($array) {
    return (count($array) != count($array, 1));
}
scronide
+6  A: 

use count() twice, one time in default mode, and one time in recursive mode. if the values match, the array is not multidimensional.

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

Nice trick, +1.
Ionuț G. Stan
A: 

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

No loops, plain and simple.

Works also with associate arrays not only numeric arrays, which could not contain 0 ( like in the previous example would throw you a warning if the array doesn't have a 0. )

Cheers

Cj

phpmember.com

Carlos