obtener - ¿Qué es más rápido: in_array() o un montón de expresiones en PHP?
obtener el valor de un array php (8)
Sugeriría que solo usando in_array()
, cualquier diferencia de velocidad sería insignificante, pero la legibilidad de probar cada variable por separado es horrible.
solo por diversión, aquí está una prueba que ejecuté:
$array = array(''test1'', ''test2'', ''test3'', ''test4'');
$var = ''test'';
$iterations = 1000000;
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if ($var != ''test1'' && $var != ''test2'' && $var != ''test3'' && $var != ''test4'') {}
}
$end = microtime(true);
print "Time1: ". ($end - $start)."<br />";
$start2 = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!in_array($var, $array) ) {}
}
$end2 = microtime(true);
print "Time2: ".($end2 - $start2)."<br />";
// Time1: 1.12536692619
// Time2: 1.57462596893
Una nota un tanto trivial a tener en cuenta, si $var
no está establecido, el método 1 tarda mucho más (dependiendo de la cantidad de condiciones que evalúe)
¿Es más rápido hacer lo siguiente?
if ($var != ''test1'' && $var != ''test2'' && $var != ''test3'' && $var != ''test4'') { ... }
O:
if (!in_array($var, array(''test1'', ''test2'', ''test3'', ''test4'') { ... }
¿Hay una cantidad de valores en qué punto es más rápido hacer uno u otro?
(En este caso, la matriz utilizada en la segunda opción ya no existe).
Tenga en cuenta que si está buscando reemplazar un montón de sentencias !==
, debe pasar el tercer parámetro a in_array
como true
, lo que impone el control de tipos en los elementos de la matriz.
Ordinary !=
No requiere esto, obviamente.
in_array será más rápido para grandes cantidades de elementos. "grande" es muy subjetivo en función de muchos factores relacionados con los datos y su computadora. Como me lo estás preguntando, asumo que no estás tratando con una cantidad trivial de ítems. Para listas más largas, preste atención a esta información y mida el rendimiento con una matriz volteada para que php pueda utilizar búsquedas de hash en lugar de una búsqueda lineal. Para una matriz "estática" que modifica puede no mejorar el rendimiento, pero también puede.
Usando el código de prueba de Owen, con una matriz volteada y más iteraciones para obtener resultados más consistentes:
$array2 = array_flip($array);
$iterations = 10000000;
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!isset($array2[$var])) {}
}
$end = microtime(true);
print "Time3: ".($end - $start)."<br />";
Time1: 12.875
Time2: 13.7037701607
Time3: 3.70514011383
Tenga en cuenta que, como señaló RoBorg, hay una sobrecarga al crear la matriz, por lo que debe moverse dentro del ciclo de iteración. Por esta razón, la publicación de Sparr también es un poco engañosa ya que hay una sobrecarga con la función array_flip.
Aquí hay otro ejemplo con las 5 variaciones:
$array = array(''test1'', ''test2'', ''test3'', ''test4'');
$var = ''test'';
$iterations = 1000000;
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if ($var != ''test1'' && $var != ''test2'' && $var != ''test3'' && $var != ''test4'') {}
}
print "Time1: ". (microtime(true) - $start);
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!in_array($var, $array) ) {}
}
print "Time2: ".(microtime(true) - $start);
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!in_array($var, array(''test1'', ''test2'', ''test3'', ''test4'')) ) {}
}
print "Time2a: ".(microtime(true) - $start);
$array2 = array_flip($array);
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!isset($array2[$var])) {}
}
print "Time3: ".(microtime(true) - $start);
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
$array2 = array_flip($array);
if (!isset($array2[$var])) {}
}
print "Time3a: ".(microtime(true) - $start);
Mis resultados:
Time1 : 0.59490108493 // straight comparison
Time2 : 0.83790588378 // array() outside loop - not accurate
Time2a: 2.16737604141 // array() inside loop
Time3 : 0.16908097267 // array_flip outside loop - not accurate
Time3a: 1.57209014893 // array_flip inside loop
En resumen, usar array_flip
(con isset) es más rápido que inarray, pero no tan rápido como una comparación directa.
Hola, llevé este caso al extremo y señalé que con un número creciente de valores, la comparación simple no es la forma más eficiente.
Aquí está mi código:
$var = ''test'';
$num_values = 1000;
$iterations = 1000000;
print "/nComparison performance test with ".$num_values." values and ".$iterations." loop iterations";
print "/n";
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if ($var != ''test0'' &&
$var != ''test1'' &&
// ...
// yes I really have 1000 lines in my file
// ...
$var != ''test999'') {}
}
print "/nCase 1: plain comparison";
print "/nTime 1: ". (microtime(true) - $start);
print "/n";
$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
$array1[] = ''test''.$i;
}
for($i = 0; $i < $iterations; ++$i) {
if (!in_array($var, $array1) ) {}
}
print "/nCase 2: in_array comparison";
print "/nTime 2: ".(microtime(true) - $start);
print "/n";
$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
$array2[''test''.$i] = 1;
}
for($i = 0; $i < $iterations; ++$i) {
if (!isset($array2[$var])) {}
}
print "/nCase 3: values as keys, isset comparison";
print "/nTime 3: ".(microtime(true) - $start);
print "/n";
$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
$array3[''test''.$i] = 1;
}
for($i = 0; $i < $iterations; ++$i) {
if (!array_key_exists($var, $array3)) {}
}
print "/nCase 4: values as keys, array_key_exists comparison";
print "/nTime 4: ".(microtime(true) - $start);
print "/n";
Mis resultados (PHP 5.5.9):
Case 1: plain comparison
Time 1: 31.616894006729
Case 2: in_array comparison
Time 2: 23.226133823395
Case 3: values as keys, isset comparison
Time 3: 0.050863981246948
Case 4: values as keys, array_key_exists comparison
Time 4: 0.13700890541077
Estoy de acuerdo, eso es un poco extremo, pero muestra el panorama general y el gran potencial en los arreglos asociativos de PHP similares a las tablas hash, solo tienes que usarlo
Cuando habla de PHP, y pregunta si:
- un conjunto de "if" sy "else ifs",
- un "si" con un conjunto de condiciones "ed" (como en los detalles de la publicación original), o
- uso de "in_array" con una matriz construida sobre la marcha,
es mejor,
uno debe tener en cuenta que la declaración de "cambio" del lenguaje PHP es una alternativa diseñada para tales situaciones y puede ser una mejor respuesta. (Aunque el ejemplo del póster nos lleva a simplemente comparar dos soluciones, el encabezado de pregunta real pide considerar in_array versus declaraciones de PHP, por lo que creo que es un juego justo).
En el ejemplo del cartel, entonces, en cambio, recomendaría:
switch ($var)
{ case ''test1'': case ''test2'': case ''test3'': case ''test4'':
echo "We have a good value"; break;
default:
echo "We do not have a good value";
}
Me gustaría que PHP permitiera un par de construcciones no primitivas en los casos, como una coma para "o". Pero lo anterior es lo que los diseñadores de PHP consideraron como la forma más clara de manejar esto. Y parece ser más eficiente en tiempo de ejecución que las otras dos alternativas también.
Mientras esté hablando de una lista de deseos, la "IN" encontrada en SQL sería aún más clara para la situación de ejemplo del póster.
Este pensamiento es probablemente lo que hace que las personas quieran usar "in_array" para tales situaciones, pero es desafortunado tener que construir una estructura de datos y luego usar un predicado diseñado para esa estructura de datos, en lugar de tener una forma de simplemente dilo sin que eso ocurra.
Sé que esta pregunta tiene casi 10 años, pero hay otras formas de hacerlo. Utilicé el método B de la página de Nick con miles de entradas. Fue increíblemente rápido.
foreach(array_values($haystack) as $v)
$new_haystack[$v] = 1;
}
// So haystack becomes:
$arr[“String1”] = 1;
$arr[“String2”] = 1;
$arr[“String3”] = 1;
// Then check for the key:
if (isset($haystack[$needle])) {
echo("needle ".$needle." found in haystack");
}
El primero será más rápido; el segundo tiene muchos gastos generales: crear la matriz, llamar a una función, buscar en la matriz ...
Sin embargo, como dije en una pregunta un par de respuestas abajo, la optimización prematura es la raíz de todo mal. Debe escribir su código para que sea legible, luego, si necesita ser optimizado, perfilelo, luego optimícelo.
Editar:
Mis tiempos con el código de @ Owen (PHP 5.2.6 / windows):
Time1: 1.33601498604
Time2: 4.9349629879
Mover la matriz (...) dentro del ciclo, como en la pregunta:
Time1: 1.34736609459
Time2: 6.29464697838