Verificando se o array é multidimensional ou não?

137
  1. Qual é a maneira mais eficiente de verificar se uma matriz é uma matriz plana de valores primitivos ou se é uma matriz multidimensional ?
  2. Existe alguma maneira de fazer isso sem realmente percorrer uma matriz e rodar is_array()em cada um de seus elementos?
Wilco
fonte
9
Vale ressaltar que o PHP não possui matrizes multidimensionais verdadeiras - apenas matrizes associativas simples de valores. Portanto, sua pergunta é realmente "existe um valor não escalar na minha matriz"?
gahooa
21
Na verdade ... acho que não vale a pena apontar.
31413 Joe

Respostas:

135

A resposta curta é não, você não pode fazê-lo sem pelo menos repetir implicitamente se a 'segunda dimensão' pode estar em qualquer lugar. Se tiver que estar no primeiro item, você faria

is_array($arr[0]);

Mas, a maneira geral mais eficiente que eu poderia encontrar é usar um loop foreach na matriz, fazendo um curto-circuito sempre que um hit é encontrado (pelo menos o loop implícito é melhor que o direto 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

Loop implícito, mas não podemos fazer um curto-circuito assim que uma correspondência for encontrada ...

$ 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
fonte
3
Bom, com a ressalva de que acredito que sua linha de filtragem deve ter array_map ("is_array", $ a), não usando is_array como uma palavra de barra.
Matthew Scharley 28/09/08
Boa captura, que acelerou is_multi, mas ainda não é bom o suficiente para jogo foreach
Vinko Vrsalovic
2
Vale a pena notar que, como está escrito, o multi_3 funcionará apenas em matrizes não associativas baseadas em zero, sem lacunas nos índices, o que significa que não identificará corretamente nenhum desses exemplos como multidimensionais.
Cragmonkey
Em função de is_multi()otimizar o código fazendoreturn count($rv)>0
Xorifelse
is_array (array_values ​​($ arr) [0]) como uma solução alternativa para chaves personalizadas.
Vitor Rodrigues
191

Use count () duas vezes; uma vez no modo padrão e uma vez no modo recursivo. Se os valores corresponderem, a matriz não é multidimensional, pois uma matriz multidimensional teria uma contagem recursiva mais alta.

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

Este segundo valor da opção modefoi adicionado no PHP 4.2.0. Nos documentos do PHP :

Se o parâmetro do modo opcional estiver definido como COUNT_RECURSIVE (ou 1), count () contará recursivamente a matriz. Isso é particularmente útil para contar todos os elementos de uma matriz multidimensional. count () não detecta recursão infinita.

No entanto, este método não detecta array(array()).

Comunidade
fonte
2
Como observado, isso não funciona para elementos com matrizes vazias
Arthur
30

Para PHP 4.2.0 ou mais recente:

function is_multi($array) {
    return (count($array) != count($array, 1));
}
scronide
fonte
Não está trabalhando para array(array())ou array(array(), array())também. Geralmente, se uma matriz interna estiver vazia, a contagem recursiva adicionará corretamente 0 a ela, fazendo com que ela corresponda à contagem normal.
Fanis Hatzidakis
13

Eu acho que esse é o caminho mais direto e é o estado da arte:

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

Você pode simplesmente executar isso:

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

Se o parâmetro do modo opcional estiver definido como COUNT_RECURSIVE(ou 1), count () contará recursivamente a matriz. Isso é particularmente útil para contar todos os elementos de uma matriz multidimensional.

Se for o mesmo, significa que não há subníveis em nenhum lugar. Fácil e rápido!

Pian0_M4n
fonte
Obrigado ... útil. Eu queria verificar se uma sub nível para minha matriz existiu, eu useiif(count($tasks_by_date) !== count($tasks_by_date, 1))
Mike Barwick
Legal. COUNT_RECURSIVE ou 1 é o mesmo para count ()
Pian0_M4n
Absolutamente. Eu apenas gosto de menos confusão e o que !==costumava ver é o subnível. Para teorias que possam estar procurando algo semelhante ... etc.
Mike Barwick
O que você tinha não estava retornando verdadeiro para mim ... eu precisava para adicionar o!==
Mike Barwick
Com matriz vazia, tem falha
Wallace Maxter
7

Você pode verificar is_array()o primeiro elemento, supondo que se o primeiro elemento de uma matriz for uma matriz, o restante deles também será.

Greg Hewgill
fonte
Esse é realmente um bom ponto. No meu caso particular, é uma situação de um ou outro, pois estou controlando a criação da matriz original. Deixarei a questão em aberto por enquanto, caso exista uma solução que possa funcionar de maneira mais geral.
209 Wilco
5
Assim:if( is_array(current($arr)) ) { // is multidimensional }
Jonas Äppelgran 31/03
4

Todas as ótimas respostas ... aqui estão minhas três linhas que eu estou sempre usando

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

Esta função retornará o número int de dimensões da matriz (roubadas daqui ).

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

   return $return;
}

fonte
Isso funcionará apenas para o caso de Greg. Não é uma solução geral para o problema em que a segunda dimensão pode ser qualquer lugar na matriz
Vinko Vrsalovic
$ arr = array ("olá", "oi" => "oi lá"); $ arr [] = & arr; // oops
Tyzoid
2

Acho que você descobrirá que essa função é a maneira mais simples, eficiente e rápida.

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

Você pode testá-lo assim:

$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';
RoboTamer
fonte
se você estiver indo para uma linha, pelo menos faça a coisa toda; foreach($a as $v) is_array($v) ? return TRUE : return FALSE;
Robert Pounder
@RobertPounder ou mesmoforeach($a as $v) return is_array($v) ? true : false;
Yassine Sedrani
2

Após o PHP 7, você poderia simplesmente fazer:

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

fonte
1

Você também pode fazer uma verificação simples 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
Prashant
fonte
1

Tente da seguinte maneira

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

}else{

  echo 'arrayList is no multidimensional';
}
Arshid KV
fonte
1

Mesmo isso funciona

is_array(current($array));

Se false, é uma matriz de dimensão única, se true, é uma matriz de dimensões múltiplas .

current fornecerá o primeiro elemento da sua matriz e verificará se o primeiro elemento é uma matriz ou não pela função is_array .

Priyank
fonte
Isso não será confiável se você quiser garantir que qualquer outro elemento também não esteja aninhado.
vanamerongen
1

Não use COUNT_RECURSIVE

clique neste site para saber por que

use rsort e depois use isset

function is_multi_array( $arr ) {
rsort( $arr );
return isset( $arr[0] ) && is_array( $arr[0] );
}
//Usage
var_dump( is_multi_array( $some_array ) );
hendra1
fonte
$ arr [0] não poderia ser e matriz, mas $ arr [1] poderia ser um array
Supun Praneeth
1

No meu caso. Eu preso em variar condição estranha.
1º caso = array("data"=> "name");
2º caso = array("data"=> array("name"=>"username","fname"=>"fname"));
Mas se datativer matriz em vez de valor, a função sizeof () ou count () não funcionará para essa condição. Então eu crio uma função personalizada para verificar.
Se o primeiro índice da matriz tiver valor, ele retornará "apenas valor".
Mas se o índice tiver matriz em vez de valor, ele retornará "tem matriz"
.

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

Agradecimentos especiais a Vinko Vrsalovic

Darkcoder
fonte
0

Eu acho que este é elegante (adereços para outro usuário não sei o nome de usuário):

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

    return count($result) == 1 && array_shift($result) == "array";
}
Alfonso Fernandez-Ocampo
fonte
0

Todos os métodos acima são complexos demais para serem implementados rapidamente. Se uma matriz é plana, o teste do primeiro elemento deve retornar uma primitiva, por exemplo, int, string etc. Se for multidimensional, deve retornar uma matriz. Por extensão, você pode usar esse liner de maneira rápida e limpa.

echo is_array(array_shift($myArray));

se isso retornar verdadeiro, a matriz é multidimensional. Caso contrário, é plana. Apenas para observar, é muito raro que matrizes tenham dimensões diferentes, por exemplo, se você estiver gerando dados de um modelo, ele sempre terá o mesmo tipo de estrutura multidimensional ou plana que pode ser atravessada por loops. laços feitos à máquina Caso contrário, você o construiu manualmente, o que significa que você sabe onde tudo estará e simplesmente funciona sem a necessidade de escrever um algoritmo de loop insira a descrição da imagem aqui

Nelson Emeka Ameyo
fonte
Essa técnica encontra somente matrizes multidimensionais se o primeiro elemento for uma matriz.
Cragmonkey
Tenha cuidado ao usar array_shift(), pois ele remove o primeiro elemento e também redefine as teclas numéricas! Melhor uso current()se ainda coçar para uma frase.
Marcello Mönkemeyer 10/02
0

Além das respostas anteriores e dependendo do esquema da matriz que você deseja 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;
}
RafaSashi
fonte
0

É tão simples quanto

$isMulti = !empty(array_filter($array, function($e) {
                    return is_array($e);
                }));
Mohd Abdul Mujib
fonte
0
$is_multi_array = array_reduce(array_keys($arr), function ($carry, $key) use ($arr) { return $carry && is_array($arr[$key]); }, true);

Aqui está um belo forro. Ele itera sobre cada chave para verificar se o valor nessa chave é uma matriz. Isso garantirá a verdadeira

Dorpo
fonte
-1
if($array[0]){
//enter your code 
}
rthcupid
fonte
Pelo menos use if (isset($array[0])) { }. Se você tem certeza índices do array começar do 0
Aistis
Uma matriz multidimensional é uma matriz que contém uma ou mais matrizes. Isso apenas verifica se ele contém um elemento com uma chave zero.
Cragmonkey
-1
if ( array_key_exists(0,$array) ) {

// multidimensional array

}  else {

// not a multidimensional array

}

* apenas para matrizes com índice numérico

sudhin babu
fonte
Uma matriz multidimensional é uma matriz que contém uma ou mais matrizes. Isso apenas verifica se ele contém um elemento com uma chave zero.
Cragmonkey 19/03/16
-1

A função print_r nativa retorna uma sequência legível por humanos. Apenas conte as instâncias "Matriz".

experimentar...

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 minha caixa, "is_multi levou 0,83681297302246 segundos em 500000 vezes"

Cortesia: Ruach HaKodesh

Racer X
fonte
-2
function isMultiArray(array $value)
{
    return is_array(reset($value));
}
jhonatan
fonte
Isso só testa se o PRIMEIRO elemento é multidimensional.
Cragmonkey 19/03
-3
is_array($arr[key($arr)]); 

Sem loops, puro e simples.

Funciona também com matrizes associadas, não apenas matrizes numéricas, que não podem conter 0 (como no exemplo anterior, seria emitido um aviso se a matriz não tivesse um 0.)

Carlos
fonte
Uma matriz não pode ser detectado na chave, você tem que verificar o valor
RoboTamer