2008-10-03 13 views
5

Si estoy profundamente en un nido de bucles Me pregunto cuál de ellos es más eficiente:Poblar una matriz de PHP: verifique primero el índice?

if (!isset($array[$key])) $array[$key] = $val; 

o

$array[$key] = $val; 

La segunda forma es mucho más deseable en la medida de código tan legible va. En realidad, los nombres son más largos y la matriz es multidimensional. Entonces, la primera forma termina pareciendo bastante retorcida en mi programa.

Pero me pregunto si la segunda forma podría ser más lenta. Dado que el código está en una de las funciones más ejecutadas en el programa, me gustaría usar la forma más rápida.

En general, este código se ejecutará muchas veces con el mismo valor de "$ key". Entonces, en la mayoría de los casos $ array [$ key] ya estará configurado, y isset() devolverá FALSE.

Para aclarar para aquellos que temen que estoy tratando el código no idéntico como si fuera idéntico: en lo que respecta a esta parte del programa, $ val es una constante. No se conoce hasta el tiempo de ejecución, pero está configurado anteriormente en el programa y no cambia aquí. Entonces ambas formas producen el mismo resultado. Y este es el lugar más conveniente para obtener $ val.

Respuesta

1

La sobrecarga de una comparación que puede o no ser cierta parece que debería llevar más tiempo.

¿Qué significa ejecutar el script en ambas configuraciones para el tiempo de rendimiento?

0

La llamada de función extra a isset() casi garantiza que tendrá más sobrecarga que cualquier asignación. Me sorprendería muchísimo si la segunda forma no es más rápida.

+0

El manual de PHP dice que "isset()" es una "construcción del lenguaje", no una función . Así que espero que la sobrecarga en realidad sea mínima. Supongo que tendré que perfilarlo y ver. –

3

isset() es muy rápido con variables ordinarias, pero tiene una matriz aquí. El algoritmo hash-map para matrices es rápido, pero aún toma más tiempo que no hacer nada.

Ahora, la primera forma puede ser más rápida si tiene más valores configurados, que los que no lo son, simplemente porque simplemente busca el hash sin recuperar o establecer el valor. Entonces, ese podría ser un punto de diferencia: elija el primer formulario si tiene más 'hits' en las teclas que están configuradas, y elija el segundo si tiene más 'errores'.

Tenga en cuenta que esos dos códigos son no idénticos. El primer formulario no establecerá el valor de alguna clave cuando ya esté configurada, ya que evita la "sobreescritura".

+0

Las dos piezas de código son efectivamente idénticas si $ val es una constante. Para mi propósito, lo es. Editado mi pregunta para aclarar esto; Gracias. –

+0

No estoy seguro si entiendo su respuesta: "elija la segunda si tiene más 'hits' en una tecla que ya está configurada". ¿Está diciendo que si $ array [$ key] ya se configurará con más frecuencia que no, debería * no * llamar a isset()? –

+0

@bslorence - tienes razón, lo arreglé ahora. –

2

¿Ha medido con qué frecuencia se encuentra con la situación que $array[$key] está configurada antes de intentar configurarlo? Creo que no se puede dar un consejo general sobre esto, porque si en realidad hay muchos de esos casos, la verificación de issi podría ahorrar algo de tiempo al evitar conjuntos no escanciados en la matriz. Sin embargo, si esto rara vez ocurre, la sobrecarga podría ralentizarte ... Lo mejor sería hacer un punto de referencia en su código real.

Sin embargo, tenga en cuenta que ambos códigos pueden dar lugar a resultados diferentes! Si $ val no es siempre el mismo para una combinación $array[$key], el código anterior siempre establecería el valor en el primer $val para ese $array[$key] donde el último código siempre lo establecería en el último valor de esa combinación.

(supongo que usted es consciente de ello y $val es siempre el mismo para $array[$key], pero algún lector detenerse por que no.)

0

¿Necesita un cheque real para ver si la clave está ahí? Con una asignación a una matriz en blanco, el isset() ralentizará el ciclo. Y a menos que haga un segundo pase con manipulación de datos, desaconsejo encarecidamente el control de isset. Esto es población, no manipulación.

10

Para una matriz que realmente desea: array_key_exists($key, $array) en lugar de isset($array[$key]).

+0

isset() es en realidad mucho más rápido. Consulte los comentarios en la página array_key_exists en el manual en línea de PHP. –

+0

Aparentemente isset() puede ser engañoso, porque devuelve FALSE si $ array [$ key] == null: http://us3.php.net/manual/en/function.array-key-exists. php # 83500 No afecta mi situación, pero vale la pena conocerla. –

+0

No si lo piensas, el valor no se establece si es igual a nulo, pero la clave de matriz aún existe. Si está eliminando algo de una matriz, debe usar unset() para evitar este problema. – Powerlord

0

YO SOY un novato en PHP, pero una combinación de ambos podrían estar con el operador ternario

$array[$key] = !isset($array[$key]) ? $val : $array[$key]; 

que es una manera de ir con él.

0

Puede ver el código fuente de PHP para ver la diferencia. No verifiqué si esto sería diferente en versiones posteriores de PHP, pero parece que en PHP3 la funcionalidad de matriz asociativa está en php3/php3_hash.c.

En los _php3_hash_exists de función, los siguientes se hacen las cosas:

  • clave es ordenado
  • cubeta correcta encontró
  • cubo caminaba, hasta el punto correcto encontró o no

_php3_hash_add_or_update Función :

  • algoritmo hash
  • cubo encontró
  • caminaron, existente anulado si existía
    • si no existiera, agregó uno nuevo

Por tanto, parece simplemente poniendo es más rápido, porque solo hay una llamada a función y esta tarea de búsqueda de cubos y hash solo se realizará una vez.

1

Debe verificar la matriz hasta, pero sin incluir, el nivel que va a establecer.

Si vamos a establecer

$anArray[ 'level1' ][ 'level2' ][ 'level3' ] = ... 

Usted debe asegurarse de que el camino hasta nivel2 existe realmente antes de establecer nivel3.

$anArray[ 'level1' ][ 'level2' ] 

No se matará a ningún cachorro si no lo hace, pero pueden molestarse dependiendo de su entorno particular.

No tiene que comprobar el índice que está configurando en realidad, ya que establecerlo automáticamente significa que está declarado, pero en aras de la buena práctica, debe asegurarse de que nada se cree mágicamente.

hay una manera fácil de hacer esto:

<?php 

function create_array_path($path, & $inArray) 
{ 
    if (! is_array($inArray)) 
    { 
     throw new Exception('The second argument is not an array!'); 
    } 
    $traversed = array(); 
    $current = &$inArray; 

    foreach($path as $subpath) 
    { 
     $traversed[] = $subpath; 
     if (! is_array($current)) 
     { 
      $current = array(); 
     } 
     if (! array_key_exists($subpath, $current)) 
     { 
      $current[ $subpath ] = ''; 
     } 
     $current = &$current[ $subpath ]; 
    } 
} 


$myArray = array(); 

create_array_path(array('level1', 'level2', 'level3'), $myArray); 

print_r($myArray); 

?> 

Esta es la salida:

Array 
    (
     [level1] => Array 
      (
       [level2] => Array 
        (
         [level3] => 
        ) 

      ) 

    ) 
Cuestiones relacionadas