php - una - ¿La forma más rápida de agregar prefijo a las claves de matriz?
prefijos y sufijos para niños (8)
¿Cuál es la forma más rápida de agregar prefijos de cadena a las claves de matriz?
Entrada
$array = array(
''1'' => ''val1'',
''2'' => ''val2'',
);
Salida necesaria:
$array = array(
''prefix1'' => ''val1'',
''prefix2'' => ''val2'',
);
Descubrí que PHPBench no es una buena fuente de puntos de referencia no triviales. Entonces, a menos que esté realmente interesado en postularse for(....);
no va a mostrar correctamente qué sintaxis será más rápida. He reunido un punto de referencia simple para demostrar que foreach es en realidad el más rápido cuando usa la clave y el valor durante la iteración.
Es muy importante forzar a PHP a leer los valores de una iteración de bucle, o hará todo lo posible para optimizarlos. En el siguiente ejemplo, uso la función doNothing
para forzar a PHP a calcular la clave y el valor cada vez. El uso de doNothing hará que se aplique una sobrecarga a cada bucle, pero será igual para cada bucle, ya que el número de llamadas será el mismo.
Realmente no estaba tan sorprendido de que foreach
llegado a la cima, ya que es la construcción del lenguaje para iterar un diccionario.
$array = range( 0, 1000000 );
function doNothing( $value, $key ) {;}
$t1_start = microtime(true);
foreach( $array as $key => $value ) {
doNothing( $value, $key );
}
$t1_end = microtime(true);
$t2_start = microtime(true);
$array_size = count( $array );
for( $key = 0; $key < $array_size; $key++ ) {
doNothing( $array[$key], $key );
}
$t2_end = microtime(true);
//suggestion from PHPBench as the "fastest" way to iterate an array
$t3_start = microtime(true);
$key = array_keys($array);
$size = sizeOf($key);
for( $i=0; $i < $size; $i++ ) {
doNothing( $key[$i], $array[$key[$i]] );
}
$t3_end = microtime(true);
$t4_start = microtime(true);
array_walk( $array, "doNothing" );
$t4_end = microtime(true);
print
"Test 1 ".($t1_end - $t1_start)."/n". //Test 1 0.342370986938
"Test 2 ".($t2_end - $t2_start)."/n". //Test 2 0.369848966599
"Test 3 ".($t3_end - $t3_start)."/n". //Test 3 0.78616809845
"Test 4 ".($t4_end - $t4_start)."/n"; //Test 4 0.542922019958
Edición: estoy usando PHP 5.3 en Mac OSX 10.6 de 64 bits
Me di cuenta de una solución de una línea:
array_walk($array, create_function(''$value, &$key'', ''$key = "prefix" . $key;''));
Me gustaría crear una matriz completamente nueva y crear sus nuevas claves. Eso tiene que ser más rápido que desactivar todas las claves no deseadas;
$prefixed_array = array();
foreach ($array as $key => $value) {
$prefixed_array[ $prefix . $key] = $value;
}
Y si quieres hacer algún otro "afijo".
function array_affix_keys($affix, Array $array, $type = ''prefix'', $options = array()){
$affixed_array = array();
if($type ==''prefix''){
foreach ($array as $key => $value) {$affixed_array[ $affix . $key] = $value;}
return $affixed_array;
}
if($type ==''suffix''){
foreach ($array as $key => $value) {$affixed_array[$key . $affix ] = $value;}
return $affixed_array;
}
if($type ==''circumfix''){
if(is_array($affix) && count($affix) == 2){
foreach ($array as $key => $value) {
$affixed_array[ $affix[0] . $key . $affix[1] ] = $value;
}
}
return $affixed_array;
}
if($type == ''simulfix'' && isset($options[''phonemes''])){
foreach ($array as $key => $value) { $affixed_array[ str_replace($options[''phonemes''], $affix, $key) ] = $value;}
return $affixed_array;
}
return $array;
}
$prefixed = array_affix_keys(''prefix_'', $array);
$prefixed = array_affix_keys(''prefix_'', $array, ''prefix'');
$suffixed = array_affix_keys(''_suffix'', $array, ''suffix'');
$circumfixed = array_affix_keys(array(''prefix'', ''suffix''), $array, ''circumfix'');
$simulfix = array_affix_keys(''replace'', $array, ''simulfix'', array(''phonemes'' => ''find''));
Otra forma de lograrlo es con array_flip ()
<?php
$data = array_flip($data);
foreach($data as $key => &$val) { $val = "prefix" . $val; }
$data = array_flip($data);
Podría hacer esto en una larga línea, supongo:
$array = array_combine(
array_map(function($k){ return ''prefix''.$k; }, array_keys($array)),
$array
);
O para versiones de PHP anteriores a 5.3:
$array = array_combine(
array_map(create_function(''$k'', ''return "prefix".$k;''), array_keys($array)),
$array
);
Probablemente hay docenas de maneras de hacer esto sin embargo:
foreach ($array as $k => $v)
{
$array[''prefix_''.$k] = $v;
unset($array[$k]);
}
Si no quieres usar para bucle puedes hacerlo:
// function called by array_walk to change the $value in $key=>$value.
function myfunction(&$value,$key) {
$value="prefix$value";
}
$keys = array_keys($array); // extract just the keys.
array_walk($keys,"myfunction"); // modify each key by adding a prefix.
$a = array_combine($keys,array_values($array)); // combine new keys with old values.
No creo que esto sea más eficiente que el bucle for
. Supongo que array_walk utilizará internamente un bucle y también hay una sobrecarga de llamada a la función aquí.
function array_key_prefix_suffix(&$array,$prefix='''',$suffix=''''){
$key_array = array_keys($array);
$key_string = $prefix.implode($suffix.'',''.$prefix,$key_array).$suffix;
$key_array = explode('','', $key_string);
$array = array_combine($key_array, $array);
}
Esto está implementado y funciona muy bien.
function keyprefix($keyprefix, Array $array) {
foreach($array as $k=>$v){
$array[$keyprefix.$k] = $v;
unset($array[$k]);
}
return $array;
}
El uso de array_flip
no conservará los valores vacíos o nulos. Se podría agregar un código adicional en el caso improbable de que la clave prefijada ya exista.