Sprawdzanie, czy tablica jest wielowymiarowa, czy nie?


137
  1. Jaki jest najskuteczniejszy sposób sprawdzenia, czy tablica jest płaską tablicą wartości pierwotnych, czy też tablicą wielowymiarową ?
  2. Czy istnieje sposób, aby to zrobić bez faktycznego przeglądania tablicy i uruchamiania is_array()na każdym z jej elementów?

9
Warto podkreślić, że PHP nie ma prawdziwych tablic wielowymiarowych - tylko proste tablice asocjacyjne wartości. Twoje pytanie naprawdę brzmi „czy w mojej tablicy jest wartość nieskalarna”?
gahooa

21
Właściwie ... nie sądzę, żeby w ogóle było to warte podkreślania.
Joe

Odpowiedzi:


135

Krótka odpowiedź brzmi: nie, nie możesz tego zrobić bez przynajmniej niejawnego zapętlenia, jeśli „drugi wymiar” może być gdziekolwiek. Jeśli ma być w pierwszej pozycji, po prostu zrób

is_array($arr[0]);

Ale najbardziej wydajnym sposobem, jaki mogłem znaleźć, jest użycie pętli foreach w tablicy, skracając za każdym razem, gdy zostanie znalezione trafienie (przynajmniej niejawna pętla jest lepsza niż prosta 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

Niejawne zapętlenie, ale nie możemy zwierać, gdy tylko zostanie znalezione dopasowanie ...

$ 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
Dobrze, z zastrzeżeniem, że uważam, że twoja linia filtrująca powinna mieć array_map ("is_array", $ a), a nie używać is_array jako zwykłego słowa.
Matthew Scharley

Dobry chwyt, który przyspieszył is_multi, ale nadal nie jest wystarczająco dobry, aby dorównać
każdemu

2
Warto zauważyć, że, jak napisano, multi_3 będzie działać tylko na niezasocjowanych tablicach zerowych bez przerw w indeksach, co oznacza, że ​​nie zidentyfikuje poprawnie żadnego z tych przykładów jako wielowymiarowych.
Cragmonkey

W funkcji is_multi()zoptymalizuj kod, wykonującreturn count($rv)>0
Xorifelse

is_array (array_values ​​($ arr) [0]) jako obejście dla niestandardowych kluczy.
Vitor Rodrigues

191

Użyj count () dwukrotnie; jeden raz w trybie domyślnym i jeden raz w trybie rekurencyjnym. Jeśli wartości są zgodne, tablica nie jest wielowymiarowa, ponieważ tablica wielowymiarowa miałaby wyższą liczbę rekurencyjną.

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

Ta druga wartość opcji modezostała dodana w PHP 4.2.0. Z dokumentów PHP :

Jeśli opcjonalny parametr trybu jest ustawiony na COUNT_RECURSIVE (lub 1), funkcja count () będzie rekurencyjnie zliczać tablicę. Jest to szczególnie przydatne do liczenia wszystkich elementów tablicy wielowymiarowej. count () nie wykrywa nieskończonej rekurencji.

Jednak ta metoda nie wykrywa array(array()).


2
Jak zauważono, to nie działa dla elementów z pustymi tablicami
Arthur,

30

Dla PHP 4.2.0 lub nowszego:

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

Nie działa dla array(array())ani array(array(), array())jednego. Ogólnie rzecz biorąc, jeśli tablica wewnętrzna jest pusta, licznik rekurencyjny poprawnie doda do niej 0, dzięki czemu będzie pasował do normalnej liczby.
Fanis Hatzidakis

13

Myślę, że jest to najprostsza droga i najnowocześniejsza:

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

9

Możesz po prostu wykonać to:

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

Jeśli opcjonalny parametr trybu jest ustawiony na COUNT_RECURSIVE(lub 1), funkcja count () będzie rekurencyjnie zliczać tablicę. Jest to szczególnie przydatne do liczenia wszystkich elementów tablicy wielowymiarowej.

Jeśli jest taki sam, oznacza to, że nigdzie nie ma podpoziomów. Łatwo i szybko!


Dzięki ... pomocna. Chciałem sprawdzić, czy istnieje poziom podrzędny mojej tablicy, użyłemif(count($tasks_by_date) !== count($tasks_by_date, 1))
Mike Barwick

Chłodny. COUNT_RECURSIVE lub 1 jest takie samo dla count ()
Pian0_M4n

Absolutnie. Po prostu lubię mniej bałaganu, a !==został użyty do zobaczenia, że ​​istnieje poziom niższy . Teorie, które mogą szukać czegoś podobnego ... itd.
Mike Barwick

To, co miałeś, nie wróciło do mnie ... Musiałem dodać!==
Mike Barwick

Z pustą tablicą zawodzi
Wallace Maxters

7

Możesz sprawdzić is_array()pierwszy element, zakładając, że jeśli pierwszy element tablicy jest tablicą, to reszta też jest.


To właściwie dobra uwaga. W moim konkretnym przypadku jest to sytuacja typu „albo / lub”, ponieważ kontroluję tworzenie oryginalnej tablicy. Na razie pozostawię to pytanie, na wypadek gdyby było rozwiązanie, które może działać bardziej ogólnie.
Wilco

5
W ten sposób:if( is_array(current($arr)) ) { // is multidimensional }
Jonas Ęppelgran

4

Wszystkie świetne odpowiedzi ... oto moje trzy linijki, których zawsze używam

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

2

Ta funkcja zwróci liczbę int wymiarów tablicy (skradzionych stąd ).

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

   return $return;
}

To zadziała tylko w przypadku Grega. To nie jest ogólne rozwiązanie problemu, w którym drugi wymiar może znajdować się w dowolnym miejscu w tablicy
Vinko Vrsalovic

$ arr = array ("cześć", "cześć" => "cześć"); $ arr [] = & arr; // Ups
Tyzoid,

2

Myślę, że przekonasz się, że ta funkcja jest najprostszym, najbardziej wydajnym i najszybszym sposobem.

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

Możesz to przetestować w ten sposób:

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

jeśli zamierzasz zająć się jedną linią, zrób przynajmniej całość; foreach($a as $v) is_array($v) ? return TRUE : return FALSE;
Robert Pounder

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

2

Po PHP 7 możesz po prostu zrobić:

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

1

Możesz również wykonać prostą kontrolę, taką jak ta:

$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

Spróbuj w następujący sposób

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

}else{

  echo 'arrayList is no multidimensional';
}

1

Nawet to działa

is_array(current($array));

Jeśli fałsz jest to tablica jednowymiarowa, jeśli prawda, to tablica wielowymiarowa .

current da ci pierwszy element twojej tablicy i sprawdzi, czy pierwszy element jest tablicą, czy nie za pomocą funkcji is_array .


Nie będzie to wiarygodne, jeśli chcesz mieć pewność, że żaden inny element również nie jest zagnieżdżony.
vanamerongen


1

W moim przypadku. Utknąłem w różnych dziwnych warunkach.
Pierwszy przypadek = array("data"=> "name");
Drugi przypadek = array("data"=> array("name"=>"username","fname"=>"fname"));
Ale jeśli datama tablicę zamiast wartości, to funkcja sizeof () lub count () nie będzie działać dla tego warunku. Następnie tworzę funkcję niestandardową do sprawdzenia.
Jeśli pierwszy indeks tablicy ma wartość to zwraca "jedyną wartość"
Ale jeśli indeks ma tablicę zamiast wartości to zwraca "ma tablicę"
Używam w ten sposób

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

Specjalne podziękowania dla Vinko Vrsalovica


0

Myślę, że ten jest elegancki (rekwizyty dla innego użytkownika, którego nie znam):

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

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

0

Wszystkie powyższe metody są zbyt skomplikowane, aby można je było szybko wdrożyć. Jeśli tablica jest płaska, testowanie pierwszego elementu powinno zwrócić prymityw, np. Int, string, itp. Jeśli jest wielowymiarowy, powinien zwrócić tablicę. Dzięki temu możesz używać tej jednej wkładki szybko i schludnie.

echo is_array(array_shift($myArray));

jeśli zwraca prawdę, tablica jest wielowymiarowa. W przeciwnym razie jest płaski. Warto zauważyć, że bardzo rzadko tablice mają różne wymiary, np. Jeśli generujesz dane z modelu, zawsze będzie on miał ten sam typ wielowymiarowej lub płaskiej struktury, przez którą można przechodzić przez pętle. pętle wykonane maszynowo Jeśli tak nie jest, to zbudowałeś go ręcznie, co oznacza, że ​​wiesz, gdzie wszystko będzie, i po prostu działa bez konieczności pisania algorytmu zapętlenia wprowadź opis obrazu tutaj


Ta technika znajduje tablice wielowymiarowe tylko wtedy, gdy pierwszy element jest tablicą.
Cragmonkey,

Zachowaj ostrożność podczas używania array_shift(), ponieważ usuwa pierwszy element, a także resetuje klawisze numeryczne! Lepiej używać, current()jeśli nadal swędzi się na jedną wkładkę.
Marcello Mönkemeyer

0

Oprócz wcześniejszych odpowiedzi iw zależności od schematu tablicy, którą chcesz sprawdzić:

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

To jest tak proste, jak

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

Oto ładna jedna wkładka. Iteruje po każdym kluczu, aby sprawdzić, czy wartość w tym kluczu jest tablicą. To zapewni prawdę


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

Przynajmniej użyj if (isset($array[0])) { }. Jeśli jesteś pewien, że indeksy tablicy zaczynają się od 0
Aistis,

Tablica wielowymiarowa to tablica zawierająca jedną lub więcej tablic. Sprawdza tylko, czy zawiera element z kluczem zerowym.
Cragmonkey

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

// multidimensional array

}  else {

// not a multidimensional array

}

* tylko do tych tablic z indeksem numerycznym


Tablica wielowymiarowa to tablica zawierająca jedną lub więcej tablic. Sprawdza tylko, czy zawiera element z kluczem zerowym.
Cragmonkey

-1

Natywna funkcja print_r zwraca ciąg czytelny dla człowieka. Po prostu policz instancje „Array”.

próbować...

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)

Na moim pudełku „is_multi zajęło 0,83681297302246 sekund 500000 razy”

Dzięki uprzejmości: Ruach HaKodesh


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

To sprawdza tylko, czy PIERWSZY element jest wielowymiarowy.
Cragmonkey

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

Bez pętli, jasne i proste.

Działa również z tablicami skojarzonymi, a nie tylko tablicami numerycznymi, które nie mogą zawierać 0 (tak jak w poprzednim przykładzie wyświetli ostrzeżenie, jeśli tablica nie ma 0).


Nie można wykryć tablicy na kluczu, musisz sprawdzić wartość
RoboTamer
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.