¿Verificando si la matriz es multidimensional o no?


137
  1. ¿Cuál es la forma más eficiente de verificar si una matriz es una matriz plana de valores primitivos o si es una matriz multidimensional ?
  2. ¿Hay alguna manera de hacer esto sin recorrer realmente una matriz y ejecutar is_array()cada uno de sus elementos?

9
Vale la pena señalar que PHP no tiene verdaderas matrices multidimensionales, solo simples matrices asociativas de valores. Entonces, su pregunta es realmente "¿hay un valor no escalar en mi matriz"?
gahooa

21
En realidad ... no creo que valga la pena señalarlo.
Joe

Respuestas:


135

La respuesta corta es no, no puede hacerlo sin al menos hacer un bucle implícito si la 'segunda dimensión' podría estar en cualquier lugar. Si tiene que estar en el primer elemento, simplemente lo haría

is_array($arr[0]);

Pero, la forma general más eficiente que pude encontrar es usar un bucle foreach en la matriz, haciendo un cortocircuito cada vez que se encuentra un golpe (al menos el bucle implícito es mejor que el directo para ()):

$ 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

Bucle implícito, pero no podemos hacer un cortocircuito tan pronto como se encuentre una coincidencia ...

$ 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
Bien, con la advertencia de que creo que su línea de filtrado debe tener array_map ("is_array", $ a), no usar is_array como una palabra simple.
Matthew Scharley

Buena captura, que aceleró is_multi, pero aún no es lo suficientemente bueno para igualar foreach
Vinko Vrsalovic

2
Vale la pena señalar que, como está escrito, multi_3 solo funcionará en matrices no asociativas basadas en cero sin espacios en los índices, lo que significa que no identificará correctamente ninguno de estos ejemplos como multidimensional.
Cragmonkey

En función, is_multi()optimice el código haciendoreturn count($rv)>0
Xorifelse

is_array (array_values ​​($ arr) [0]) como solución alternativa para claves personalizadas.
Vitor Rodrigues

191

Use count () dos veces; una vez en modo predeterminado y una vez en modo recursivo. Si los valores coinciden, la matriz no es multidimensional, ya que una matriz multidimensional tendría un recuento recursivo más alto.

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

El segundo valor de esta opción modese agregó en PHP 4.2.0. De los documentos PHP :

Si el parámetro de modo opcional se establece en COUNT_RECURSIVE (o 1), count () contará recursivamente la matriz. Esto es particularmente útil para contar todos los elementos de una matriz multidimensional. count () no detecta recursión infinita.

Sin embargo, este método no detecta array(array()).


2
Como se señaló, esto no funciona para elementos con matrices vacías
Arthur

30

Para PHP 4.2.0 o más reciente:

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

No funciona para array(array())o array(array(), array())tampoco. En general, si una matriz interna está vacía, entonces el recuento recursivo agregará correctamente 0, haciendo que coincida con el recuento normal.
Fanis Hatzidakis

13

Creo que esta es la forma más directa y es lo más avanzado:

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

9

Simplemente puede ejecutar esto:

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

Si el parámetro de modo opcional se establece en COUNT_RECURSIVE(o 1), count () contará recursivamente la matriz. Esto es particularmente útil para contar todos los elementos de una matriz multidimensional.

Si es lo mismo, significa que no hay subniveles en ninguna parte. ¡Fácil y rápido!


Gracias ... útil Quería comprobar que existía un subnivel para mi matriz, solíaif(count($tasks_by_date) !== count($tasks_by_date, 1))
Mike Barwick el

Frio. COUNT_RECURSIVE o 1 es igual para count ()
Pian0_M4n el

Absolutamente. Simplemente me gusta menos desorden y el que !==solía ver es que existía un subnivel. Para teorías que podrían estar buscando algo similar ... etc.
Mike Barwick

Lo que tenías no me estaba volviendo cierto ... necesitaba agregar el!==
Mike Barwick

Con matriz vacía, falla
Wallace Maxters

7

Puede ver is_array()el primer elemento, bajo el supuesto de que si el primer elemento de una matriz es una matriz, entonces el resto de ellos también lo son.


Eso es realmente un buen punto. En mi caso particular, es una situación de uno o dos, ya que estoy controlando la creación de la matriz original. Dejaré la pregunta abierta por ahora en caso de que haya una solución que funcione de manera más general.
Wilco

55
Así:if( is_array(current($arr)) ) { // is multidimensional }
Jonas Äppelgran

4

Todas excelentes respuestas ... aquí están mis tres líneas que siempre uso

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

2

Esta función devolverá int número de dimensiones de la matriz (robado de aquí ).

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

   return $return;
}

Esto solo funcionará para el caso de Greg. No es una solución general al problema donde la segunda dimensión podría estar en cualquier lugar de la matriz
Vinko Vrsalovic

$ arr = array ("hola", "hola" => "hola"); $ arr [] = & arr; // oops
Tyzoid

2

Creo que encontrará que esta función es la forma más simple, más eficiente y más rápida.

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

Puedes probarlo así:

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

si vas a una línea, al menos haz todo; foreach($a as $v) is_array($v) ? return TRUE : return FALSE;
Robert Pounder

@RobertPounder o inclusoforeach($a as $v) return is_array($v) ? true : false;
Yassine Sedrani

2

Después de PHP 7, simplemente podría hacer:

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

1

También puede hacer una comprobación simple como esta:

$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

Intenta lo siguiente

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

}else{

  echo 'arrayList is no multidimensional';
}

1

Incluso esto funciona

is_array(current($array));

Si es falso, es una matriz de una sola dimensión. Si es verdadero, es una matriz de múltiples dimensiones .

current le dará el primer elemento de su matriz y verificará si el primer elemento es una matriz o no por la función is_array .


Eso no será confiable si desea asegurarse de que ningún otro elemento tampoco esté anidado.
vanamerongen


1

En mi caso. Me atasqué en diferentes condiciones extrañas.
1. ° caso = array("data"=> "name");
2. ° caso = array("data"=> array("name"=>"username","fname"=>"fname"));
Pero si datatiene una matriz en lugar de un valor, la función sizeof () o count () no funciona para esta condición. Luego creo una función personalizada para verificar.
Si el primer índice de la matriz tiene valor, entonces devuelve "solo valor"
Pero si el índice tiene una matriz en lugar de valor, entonces devuelve "tiene matriz"
.

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

Un agradecimiento especial a Vinko Vrsalovic


0

Creo que este es elegante (accesorios para otro usuario, no sé su nombre de usuario):

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

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

0

Todos los métodos anteriores son demasiado complejos para un despliegue rápido. Si una matriz es plana, probar el primer elemento debería devolver una primitiva, por ejemplo int, string, etc. Si es multidimensional, debería devolver una matriz. Por extensión, puede usar este forro rápido y ordenado.

echo is_array(array_shift($myArray));

Si esto devuelve verdadero, la matriz es multidimensional. De lo contrario, es plano. Solo para tener en cuenta, es muy raro que las matrices tengan diferentes dimensiones, por ejemplo, si está generando datos a partir de un modelo, siempre tendrá el mismo tipo de estructura multidimensional o plana que puede ser atravesada por bucles. bucles hechos a máquina Si no lo es, entonces lo ha creado a mano, lo que significa que sabe dónde estará todo y simplemente funciona sin necesidad de escribir un algoritmo de bucle. ingrese la descripción de la imagen aquí


Esta técnica solo encuentra matrices multidimensionales si el primer elemento es una matriz.
Cragmonkey

Tenga cuidado con el uso array_shift(), ya que elimina el primer elemento y también restablece las teclas numéricas. Mejor uso current()si todavía te pica por una sola línea.
Marcello Mönkemeyer

0

Además de las respuestas anteriores y dependiendo del esquema de la matriz que desea verificar:

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

Es tan simple como

$isMulti = !empty(array_filter($array, function($e) {
                    return is_array($e);
                }));

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

Aquí hay un buen trazador de líneas. Se itera sobre cada clave para verificar si el valor en esa clave es una matriz. Esto asegurará cierto


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

Al menos uso if (isset($array[0])) { }. Si está seguro de que los índices de la matriz comienzan desde 0
Aistis

Una matriz multidimensional es una matriz que contiene una o más matrices. Esto solo verifica si contiene un elemento con una clave de cero.
Cragmonkey

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

// multidimensional array

}  else {

// not a multidimensional array

}

* solo a aquellas matrices con índice numérico


Una matriz multidimensional es una matriz que contiene una o más matrices. Esto solo verifica si contiene un elemento con una clave de cero.
Cragmonkey

-1

La función print_r nativa devuelve una cadena legible por humanos. Solo cuente las instancias de "Array".

tratar...

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)

En mi caja, "is_multi tardó 0.83681297302246 segundos en 500000 veces"

Cortesía: Ruach HaKodesh


-2
function isMultiArray(array $value)
{
    return is_array(reset($value));
}

Esto solo prueba si el PRIMER elemento es multidimensional.
Cragmonkey

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

Sin bucles, simple y llanamente.

Funciona también con matrices asociadas, no solo matrices numéricas, que no pueden contener 0 (como en el ejemplo anterior, le daría una advertencia si la matriz no tiene un 0).


No se puede detectar una matriz en la clave, debe verificar el valor
RoboTamer
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.