Cuando estáis desarrollando en PHP, como nosotros con WordPress o WooCommerce, en más de una ocasión por ejemplo cuando haces una llamada a un filtro en WordPress y devuelves un array, te gustaría hacerlo ordenado de otra forma. Cosas que se me ocurren: elemento de «Mi cuenta» en WooCommerce, métodos de envío en WooCommerce o tantos otros. El caso es que muchos de estos array están referenciados a una cadena, lo que también llamamos matriz asociativa, array asociativo o tabla hash; y no es tan inmediato reordenarlos.
Pues bueno como es un problema con el que me enfrento a menudo, voy a describir unas pocas soluciones.
Os doy primero el array con los datos y el array que marcará el orden.
$datos_usuario = array(
'first_name' => 'Javier',
'user_email' => 'carazo@codection.com',
'last_login' => '2020-01-25',
'last_name' => 'Carazo'
);
$orden = array('first_name', 'last_name', 'user_email', 'last_login'); El resultado que deseamos es el siguiente por lo tanto:
$datos_usuario = array( 'first_name' => 'Javier', 'last_name' => 'Carazo', 'user_email' => 'carazo@codection.com', 'last_login' => '2020-01-25' );
Veamos tres formas diferentes de hacerlo.
$array_ordenado = array_merge( array_flip( $orden ), $datos_usuario );
$array_ordenado = array_replace( array_flip( $orden ), $datos_usuario );
uksort( $datos_usuario, function( $key1, $key2 ) use ( $orden ) {
return ( ( array_search( $key1, $orden ) > array_search( $key2, $orden ) ) ? 1 : -1 );
}); Por gustarme más me gusta más uno de los dos primeros métodos (por su limpieza de código), aunque si en los comentarios podéis aportar vuestros pensamientos de cuál de ellas es más rápida, será interesante saberlo para cuando el array a ordenar sea de cierto tamaño. Y si conocéis otro método más, encantado de que lo aportéis.
Gracias a la aportación de Manuel Canga, en este tweet:
Incluimos otro método más basado en el uso de foreach:
foreach( $order as $field ){
$datos_usuario_ordenado[ $field ] = $datos_usuario[ $field ];
} Seguimos actualizando este post y es que Manuel Canga ha tenido el detalle de calcular tiempos, para ver cuál es más rápido y aquí os dejo el resultado. Tenéis la ejecución online aquí en PHP Sandbox.
Array merge: 1580140177.172296
Array replace: 1580140177.453599
Array uksort: 1580140178.319940
Foreach: 1580140178.606628
<?php
const MAX_LOOPS = 1000000; // 1 million
$datos_usuario = array(
'first_name' => 'Javier',
'user_email' => 'carazo@codection.com',
'last_login' => '2020-01-25',
'last_name' => 'Carazo'
);
$orden = array('first_name', 'last_name', 'user_email', 'last_login');
$time_start = microtime(true);
for($i = 0; $i<MAX_LOOPS; $i++ ) {
$array_ordenado = array_merge( array_flip( $orden ), $datos_usuario );
}
$time_end = microtime(true);
printf("\nArray merge: %f", $time_end);
//-------
$time_start = microtime(true);
for($i = 0; $i<MAX_LOOPS; $i++ ) {
$array_ordenado = array_replace( array_flip( $orden ), $datos_usuario );
}
$time_end = microtime(true);
printf("\nArray replace: %f", $time_end);
//-------
$time_start = microtime(true);
for($i = 0; $i<MAX_LOOPS; $i++ ) {
uksort( $datos_usuario, function( $key1, $key2 ) use ( $orden ) {
return ( ( array_search( $key1, $orden ) > array_search( $key2, $orden ) ) ? 1 : -1 );
});
}
$time_end = microtime(true);
printf("\nArray uksort: %f", $time_end);
//-------
$time_start = microtime(true);
for($i = 0; $i<MAX_LOOPS; $i++ ) {
$array_ordenado = [];
foreach($orden as $field ) {
$array_ordenado[$field] = $datos_usuario[$field];
}
}
$time_end = microtime(true);
printf("\nForeach: %f", $time_end);
Se han hecho un total de 1 millón de iteraciones sobre cada operación para así ver el rendimiento de cada instrucción, sobre esta estructura de datos. Otra prueba diferente sería ordenar una estructura de datos grande (que no tienen por qué ser igual los resultados) y de estos resultados podemos deducir que en estructuras pequeñas como esta:
Y por lo tanto, os invito a hacerlo como más os guste. A mí personalmente me gustan más los primeros también por su sencillez a la hora de escribirlos, así que me quedo con ellos por dos motivos, sencillo y rápido.
Si tenéis más aportaciones, ya sabéis a través de tweets o comentarios podemos agregarlas.Nota: Hay una valoración incrustada en esta entrada, por favor, visita esta entrada para valorarla.
Por qué falla Bizum WooCommerce: detecta errores de credenciales, firma, entorno y pedidos para recuperar…
Elige un plugin gratuito Redsys WordPress con criterio: compatibilidad, seguridad, configuración bancaria y límites para…
¿Qué necesito para activar CECA Online? Revisa contrato bancario, datos del terminal, seguridad, pruebas y…
Aprende a elegir una pasarela para suscripciones en WordPress: revisa recurrencia, compatibilidad, seguridad y soporte…
Elige un plugin Bizum WordPress compatible con tu flujo de venta, configura la pasarela bancaria…
Aprende cómo aceptar CECA en reservas WordPress, configurar pagos seguros y confirmar cada reserva sin…