Verifica se l'array è multidimensionale o no?


137
  1. Qual è il modo più efficiente per verificare se un array è un array piatto di valori primitivi o se è un array multidimensionale ?
  2. Esiste un modo per farlo senza effettivamente passare in rassegna un array e in esecuzione is_array()su ciascuno dei suoi elementi?

9
Vale la pena sottolineare che PHP non ha veri array multidimensionali, ma solo semplici array associativi di valori. Quindi la tua domanda è davvero "c'è un valore non scalare nel mio array"?
gahooa,

21
In realtà ... non penso che valga la pena sottolineare.
Joe,

Risposte:


135

La risposta breve è no, non puoi farlo senza almeno ricorrere in modo implicito se la "seconda dimensione" potrebbe essere ovunque. Se deve essere nel primo elemento, lo faresti semplicemente

is_array($arr[0]);

Ma il modo generale più efficace che ho trovato è usare un ciclo foreach sull'array, cortocircuitando ogni volta che viene trovato un hit (almeno il loop implicito è migliore del straight per ()):

$ 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

Looping implicito, ma non possiamo cortocircuitare non appena viene trovata una corrispondenza ...

$ 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
Bene, con l'avvertenza che ritengo che la tua linea di filtro dovrebbe avere array_map ("is_array", $ a), non usando is_array come parola nuda.
Matthew Scharley,

Buona cattura, che ha accelerato is_multi, ma non è ancora abbastanza buono da eguagliare foreach
Vinko Vrsalovic,

2
Vale la pena notare che, come scritto, multi_3 funzionerà solo su array non associativi a base zero senza lacune negli indici, il che significa che non identificherà correttamente nessuno di questi esempi come multidimensionali.
Cragmonkey

In funzione, is_multi()ottimizza il codice facendo:return count($rv)>0
Xorifelse,

is_array (array_values ​​($ arr) [0]) come soluzione alternativa per chiavi personalizzate.
Vitor Rodrigues,

191

Usa due volte count (); una volta in modalità predefinita e una volta in modalità ricorsiva. Se i valori corrispondono, l'array non è multidimensionale, poiché un array multidimensionale avrebbe un conteggio ricorsivo più elevato.

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

Questa seconda opzione valore è modestata aggiunta in PHP 4.2.0. Dai documenti PHP :

Se il parametro della modalità opzionale è impostato su COUNT_RECURSIVE (o 1), count () conterà ricorsivamente l'array. Ciò è particolarmente utile per contare tutti gli elementi di un array multidimensionale. count () non rileva la ricorsione infinita.

Tuttavia, questo metodo non rileva array(array()).


2
Come notato, questo non funziona con elementi con array vuoti
Arthur,

30

Per PHP 4.2.0 o successivi:

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

Non lavora per array(array())o array(array(), array())entrambi. Generalmente, se un array interno è vuoto, il conteggio ricorsivo aggiungerà correttamente 0 per esso, facendolo corrispondere al conteggio normale.
Fanis Hatzidakis,

13

Penso che questo sia il modo più semplice ed è allo stato dell'arte:

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

9

Puoi semplicemente eseguire questo:

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

Se il parametro della modalità opzionale è impostato su COUNT_RECURSIVE(o 1), count () conterà ricorsivamente l'array. Ciò è particolarmente utile per contare tutti gli elementi di un array multidimensionale.

Se è lo stesso, significa che non ci sono livelli secondari da nessuna parte. Facile e veloce!


Grazie ... utile. Volevo verificare l'esistenza di un sotto-livello del mio array, ho usatoif(count($tasks_by_date) !== count($tasks_by_date, 1))
Mike Barwick il

Freddo. COUNT_RECURSIVE o 1 è lo stesso per count ()
Pian0_M4n

Assolutamente. Mi piace solo meno disordine e l' !==usato per vedere se esisteva un livello secondario. Per le teorie che potrebbero cercare qualcosa di simile ... ecc.
Mike Barwick,

Quello che avevi non stava tornando vero per me ... Avevo bisogno di aggiungere!==
Mike Barwick il

Con array vuoto, ha esito negativo
Wallace Maxters,

7

Si potrebbe verificare is_array()il primo elemento, supponendo che se il primo elemento di un array è un array, lo sono anche gli altri.


Questo è in realtà un buon punto. Nel mio caso particolare, è una situazione o / o poiché sto controllando la creazione dell'array originale. Lascerò la domanda aperta per ora nel caso in cui ci sia una soluzione che potrebbe funzionare più in generale però.
Wilco,

5
In questo modo:if( is_array(current($arr)) ) { // is multidimensional }
Jonas Äppelgran

4

Tutte ottime risposte ... ecco le mie tre righe che utilizzo sempre

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

2

Questa funzione restituirà il numero int delle dimensioni dell'array (rubato da qui ).

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

   return $return;
}

Questo funzionerà solo per il caso di Greg. Non è una soluzione generale al problema in cui la seconda dimensione potrebbe trovarsi ovunque nell'array
Vinko Vrsalovic,

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

2

Penso che scoprirai che questa funzione è il modo più semplice, più efficiente e più veloce.

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

Puoi provarlo in questo modo:

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

se hai intenzione di fare una riga, almeno fai tutto; foreach($a as $v) is_array($v) ? return TRUE : return FALSE;
Robert Pounder,

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

2

Dopo PHP 7 potresti semplicemente fare:

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

1

Puoi anche fare un semplice controllo come questo:

$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

Prova come segue

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

}else{

  echo 'arrayList is no multidimensional';
}

1

Anche questo funziona

is_array(current($array));

Se false è un array a dimensione singola, se true è un array a più dimensioni .

current ti darà il primo elemento del tuo array e controllerà se il primo elemento è un array o meno con la funzione is_array .


Non sarà affidabile se vuoi assicurarti che nessun altro elemento sia nidificato.
Vanamerongen,

1

Non utilizzare COUNT_RECURSIVE

fai clic su questo sito per sapere perché

usa rsort e quindi usa 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] non può essere e array ma $ arr [1] potrebbe essere un array
Supun Praneeth

1

Nel mio caso. Mi sono bloccato in varie condizioni strane.
1st case = array("data"=> "name");
2nd case = array("data"=> array("name"=>"username","fname"=>"fname"));
Ma se dataha array invece di value, la funzione sizeof () o count () non funziona per questa condizione. Quindi creo una funzione personalizzata da controllare.
Se il primo indice dell'array ha un valore, allora restituisce "solo valore"
Ma se l'indice ha un array invece del valore, allora restituisce "ha un array"
Uso così

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

Un ringraziamento speciale a Vinko Vrsalovic


0

Penso che questo sia di classe (prop a un altro utente non conosco il suo nome utente):

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

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

0

Tutti i metodi sopra indicati sono troppo complessi per essere implementati rapidamente. Se una matrice è piatta, testare il primo elemento dovrebbe restituire una primitiva, ad esempio int, stringa, ecc. Se è multidimensionale, dovrebbe restituire una matrice. Per estensione, puoi usare questa fodera in modo rapido e pulito.

echo is_array(array_shift($myArray));

se questo restituisce true, l'array è multidimensionale. Altrimenti è piatto. Solo per notare, è molto raro che le matrici abbiano dimensioni diverse, ad esempio se si stanno generando dati da un modello, avrà sempre lo stesso tipo di struttura multidimensionale o piatta che può essere attraversata da loop. anelli realizzati a macchina In caso contrario, lo hai personalizzato a mano, il che significa che sai dove sarà tutto e funziona senza la necessità di scrivere un algoritmo di loop inserisci qui la descrizione dell'immagine


Questa tecnica trova array multidimensionali solo se il primo elemento è un array.
Cragmonkey

Fai attenzione quando usi array_shift(), poiché rimuove il primo elemento e ripristina anche i tasti numerici! Meglio usare current()se ancora prurito per una fodera.
Marcello Mönkemeyer,

0

Oltre alle risposte precedenti e in base allo schema dell'array che si desidera verificare:

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

È semplice come

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

Ecco una bella fodera. Esamina ogni chiave per verificare se il valore in quella chiave è un array. Questo assicurerà vero


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

Almeno usare if (isset($array[0])) { }. Se sei sicuro che gli indici dell'array inizieranno da 0
Aistis,

Un array multidimensionale è un array che contiene uno o più array. Questo controlla solo se contiene un elemento con una chiave pari a zero.
Cragmonkey

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

// multidimensional array

}  else {

// not a multidimensional array

}

* solo per quelle matrici con indice numerico


Un array multidimensionale è un array che contiene uno o più array. Questo controlla solo se contiene un elemento con una chiave pari a zero.
Cragmonkey

-1

La funzione nativa print_r restituisce una stringa leggibile dall'uomo. Basta contare le istanze "Array".

provare...

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)

Nella mia scatola, "is_multi ha impiegato 0,83681297302246 secondi in 500000 volte"

Per gentile concessione: Ruach HaKodesh


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

Questo verifica solo se il PRIMO elemento è multidimensionale.
Cragmonkey

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

Nessun loop, chiaro e semplice.

Funziona anche con array associati non solo array numerici, che non possono contenere 0 (come nell'esempio precedente, ti darebbe un avvertimento se l'array non ha uno 0)


Non è possibile rilevare un array sulla chiave, è necessario verificare il valore
RoboTamer
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.