O que é mais rápido e melhor para determinar se existe uma chave de matriz no PHP?

157

Considere estes 2 exemplos ...

$key = 'jim';

// example 1
if (isset($array[$key])) {
    // ...
}

// example 2    
if (array_key_exists($key, $array)) {
    // ...
}

Estou interessado em saber se um deles é melhor. Eu sempre usei o primeiro, mas já vi muitas pessoas usarem o segundo exemplo neste site.

Então, qual é o melhor? Mais rápido? Intenção mais clara?

alex
fonte
Eu não corri nenhum benchmark, não. Devo ter antes de perguntar?
315 de alex
4
issetnunca se comportará exatamente como array_key_existsno exemplo de código que supostamente o faz se comportar de forma idêntica emite um aviso se a chave não existir.
deceze
Que tal in_array? maettig.com/1397246220
DanMan
1
@ DanMan, in_arrayé O(n)porque verifica os valores e não as chaves. Eles quase sempre serão mais lentos, a menos que o seu nseja extremamente pequeno.
Pacerier 8/03/15
Por que não $array[$key] === null?
Pacerier 2/17/17

Respostas:

237

isset()é mais rápido, mas não é o mesmo que array_key_exists().

array_key_exists()puramente verifica se a chave existe, mesmo que o valor seja NULL.

Considerando isset()que retornará falsese a chave existir e o valor for NULL.

Richard Levasseur
fonte
5
Você tem recursos específicos alegando que o isset é mais rápido?
Francesco Pasa
@Francesco Pasa Basta pensar um pouco. issetnão é uma função de pesquisa de matriz, apenas verifica a presença de uma variável na tabela de símbolos e não itera sobre a matriz. array_key_existspor outro lado, iterará / procurará as chaves na primeira dimensão da matriz especificada.
Rain
@Rain Tenho certeza de array_key_exists()que apenas verificará se a chave está na matriz, o que significa que ela não fará uma pesquisa, pois é uma tabela de hash.
Francesco Pasa
@FrancescoPasa Bem, "procurar as chaves" é o que a documentação do PHP diz. Fora isso, não sei dizer se "pesquisar" para eles significa algo completamente diferente do que significa para mim.
Chuva
32

Se você estiver interessado em alguns testes que fiz recentemente:

https://stackoverflow.com/a/21759158/520857

Resumo:

| Method Name                              | Run time             | Difference
=========================================================================================
| NonExistant::noCheckingTest()            | 0.86004090309143     | +18491.315775911%
| NonExistant::emptyTest()                 | 0.0046701431274414   | +0.95346080503016%
| NonExistant::isnullTest()                | 0.88424181938171     | +19014.461681183%
| NonExistant::issetTest()                 | 0.0046260356903076   | Fastest
| NonExistant::arrayKeyExistsTest()        | 1.9001779556274      | +209.73055713%
Populus
fonte
IMPORTANTE: o tempo do arrayKeyExists foi descoberto como muito errado - estava verificando o valor e não a chave - siga esse link para o tempo revisado no 7.1, que é muito melhor. (Também seria melhor em versões anteriores do PHP, se Populus refiz o teste.)
ToolmakerSteve
19

Bem, a principal diferença é que isset()não retornará truechaves de matriz que correspondam a um valor nulo, enquanto array_key_exists()isso ocorre.

A execução de um pequeno benchmark mostra que isset()é mais rápido, mas pode não ser totalmente preciso.

CMS
fonte
1
Você pode executar o benchmark novamente com o mais correto "(isset ($ array [$ i]) || $ array [$ i] === null)"?
Tomalak
Ah, e você indicaria quanta diferença de desempenho as duas variantes mostram? Obrigado!
Tomalak
1
@Tomalak, executei o exemplo que você sugeriu e afirma que array_key_exists () é mais rápido que isset () com o || operador. #
alex
1
Acima dos mortos ... mas também refiz o benchmark e fiz um ajuste para que o segundo loop for inicialize seu próprio contador e limpe a matriz de resultados. Ele mostra "isset || nulo" sendo mais rápido. codepad.org/Np6oPvgS
KyleWpppd
3
@Tomalak, isset($array[$i]) || $array[$i] === nullnão faz sentido, pois retornará truepara todos os casos. Você nunca será falso, isset($array[$i]) || $array[$i] === nullindependentemente das entradas.
Pacerier 8/03/15
10

Eu queria adicionar meus 2 centavos nessa questão, pois estava faltando uma saída intermediária.

Como já foi dito isset(), avaliará o valor da chave, para que ele retorne falsese esse valor estiver nullonde array_key_exists()apenas verificará se a chave existe na matriz.


Eu executei uma referência simples usando o PHP 7, os resultados mostrados são o tempo que levou para concluir a iteração:

$a = [null, true];

isset($a[0])                            # 0.3258841  - false
isset($a[1])                            # 0.28261614 - true
isset($a[2])                            # 0.26198816 - false

array_key_exists(0, $a)                 # 0.46202087 - true
array_key_exists(1, $a)                 # 0.43063688 - true
array_key_exists(2, $a)                 # 0.37593913 - false

isset($a[0]) || array_key_exists(0, $a) # 0.66342998 - true
isset($a[1]) || array_key_exists(1, $a) # 0.28389215 - true
isset($a[2]) || array_key_exists(2, $a) # 0.55677581 - false

array_key_isset(0, $a)                  # 1.17933798 - true
array_key_isset(1, $a)                  # 0.70253706 - true
array_key_isset(2, $a)                  # 1.01110005 - false

Adicionei os resultados dessa função personalizada a este benchmark para concluir:

function array_key_isset($k, $a){
    return isset($a[$k]) || array_key_exists($k, $a);
}

Como visto e já dito, isset()é o método mais rápido, mas pode retornar falso se o valor for null. Isso pode dar resultados indesejados e, geralmente, deve- array_key_exists()se usar se for esse o caso.

No entanto, existe uma saída intermediária e isso está sendo usado isset() || array_key_exists(). Esse código geralmente usa a função mais rápida isset()e, se isset() retornar falso somente, use array_key_exists()para validar. Mostrado na tabela acima, é tão rápido quanto chamar claramente isset().

Sim, é um pouco mais para escrever e agrupá-lo em uma função é mais lento, mas muito mais fácil. Se você precisar disso para obter desempenho, verifique os big data, etc, escreva-os na íntegra, caso contrário, se o seu uso único for muito pequeno, a sobrecarga na função array_key_isset()será insignificante.

Xorifelse
fonte
7

Com o Php 7, é possível usar o Operador de coalescência nulo .

O operador coalescente nulo (??) foi adicionado como açúcar sintático para o caso comum de precisar usar um ternário em conjunto com isset (). Retorna seu primeiro operando se existir e não for NULL; caso contrário, ele retornará seu segundo operando.

Portanto, agora você pode atribuir um valor padrão caso o valor seja nulo ou se a chave não existir:

$var = $array[$key] ?? 'default value'
John
fonte
6

existe uma diferença do php.net que você lerá:

isset () não retorna TRUE para chaves de matriz que correspondem a um valor NULL, enquanto array_key_exists () sim.

Um teste muito informal mostra array_key_exists()ser cerca de 2,5 vezes mais lento queisset()

Scott Evernden
fonte
3

Combinando isset()e is_null()dar o melhor desempenho em relação a outras funções como: array_key_exists(), isset(), isset()+ array_key_exists(), is_null(), isset()+ is_null(), a única questão aqui é a função não só irá retornar false se a chave não existir, mas até mesmo a exist chave e tem um valor nulo.

Script de benchmark:

<?php
  $a = array('a' => 4, 'e' => null)

  $s = microtime(true); 
  for($i=0; $i<=100000; $i++) { 
    $t = (isset($a['a'])) && (is_null($a['a'])); //true 
    $t = (isset($a['f'])) && (is_null($a['f'])); //false
    $t = (isset($a['e'])) && (is_null($a['e']));; //false 
  } 

  $e = microtime(true); 
  echo 'isset() + is_null() : ' , ($e-$s)."<br><br>";
?>

Crédito : http://www.zomeoff.com/php-fast-way-to-determine-a-key-elements-existance-in-an-array/

H Aßdøµ
fonte
1

Quanto a "mais rápido": experimente (meu dinheiro está ativo array_key_exists(), mas não posso fazê-lo agora).

Quanto a "mais claro na intenção": array_key_exists()

Tomalak
fonte
3
O isset () é realmente significativamente mais rápido se você não se importa com o comportamento nulo (consulte randombenchmarks.com/?p=29 ).
31415 Matt Kantor
0

Obviamente, o segundo exemplo é mais claro na intenção, não há dúvida sobre isso. Para descobrir o que o exemplo nº 1 faz, você precisa estar familiarizado com as idiossincrasias de inicialização de variáveis ​​do PHP - e então descobrirá que ele funciona de maneira diferente para valores nulos, e assim por diante.

Quanto ao que é mais rápido - não pretendo especular - corra em um loop apertado algumas centenas de milhares de vezes na sua versão PHP e você descobrirá :)

Mihai Limbășan
fonte
-2

Seu código isset($array[$i]) || $array[$i] === nullretornará verdadeiro em todos os casos, mesmo que a chave não exista (e produza um aviso de índice indefinido). Para o melhor desempenho, o que você deseja éif (isset($array[$key]) || array_key_exists($key,$array)){doWhatIWant();}

Jacaré
fonte
1
A única vez que $array[$i] === nullserá executado é quando $ i existe na matriz e ter o valor NULL ..
Niclas Larsson