Reemplazar bucles básicos por las funciones nativas de arrays en PHP

¡Hola hola! Soy Juan Ramón González Morales, programando PHP en Jaén. Aquí estamos con un nuevo post. En este post voy a hablar acerca de mejorar la complejidad ciclomática. Reducir el uso de bucles básicos y reemplazarlos en la medida de lo posible por las funciones nativas de los arrays de PHP.

Además, pondré unos ejemplos de qué tipo de instrucciones y bucles pueden ser sustituidas por las funciones básicas.

Complejidad ciclomática

La Complejidad Ciclomática (en inglés, Cyclomatic Complexity) es una métrica del software en ingeniería del software que proporciona una medición cuantitativa de la complejidad lógica de un programa.

La complejidad ciclomática es una de las métricas de software de mayor aceptación, ya que ha sido concebida para ser independiente del lenguaje.

Esta métrica mide el número de flujos distintos de ejecución que puede tener el código de un programa de software. En resumen, nos dice cuantos ifs-then-elsewhileforswitch…etc, tenemos en nuestro código.

Funciones array nativas de PHP

Hay muchas funciones array nativas, que al ser nativas mejoran la eficiencia. El uso de las funciones nativas está sobradamente comprobado, además de mejorar su eficiencia con cada nueva versión de PHP.

La costumbre, nos lleva a crear más loops de los que necesitamos, muchas veces por desconocimiento de las propias funciones nativas. Usar las funciones nativas podrían hacer nuestro código más claro y más legible de una manera sencilla.

Indexar datos según una columna usando array_column

Un código que he visto en distintas compañías y distintos proyectos para recibir datos de la base de datos y devolverlo en un array indexado por id. Es un código muy común y que seguro que se repite en casi todos los proyectos web y PHP.

Os voy a poner un pequeño ejemplo. Indexar datos según una columna del conjunto de datos. En el ejemplo siguiente, vamos a ordenar los datos recibidos en un array, según el ID.

<?php
$datos = [
    ['id' => 111, 'nombre' => 'nombre1', 'edad'=>1],
    ['id' => 112, 'nombre' => 'nombre2', 'edad'=>2],
    ['id' => 113, 'nombre' => 'nombre3', 'edad'=>3],
];

$resultado = [];
foreach ($datos as $key => $dato) {
  $resultado[$dato['id']] = $dato;
}
print_r($resultado);
// Output
// Array
// (
//     [111] => Array
//         (
//             [id] => 111
//             [nombre] => nombre1
//             [edad] => 1
//         )
//     [112] => Array
//         (
//             [id] => 112
//             [nombre] => nombre2
//             [edad] => 2
//         )
//     [113] => Array
//         (
//             [id] => 113
//             [nombre] => nombre3
//             [edad] => 3
//         )
// )

Podemos ver básicamente, como lo que obtenemos es un array ordenado por el id de los datos del array inicial. Para llegar a este resultado, hemos creado un array auxiliar para guardar los datos, así como el bucle para añadirlos.

Bien, el código anterior puede ser sustituido por la función nativa array_column con lo que sabiendo lo que hace la función quedaría el código así.

A la función nativa se le pasan 3 parámetros:

  • 1: El array que contiene la información que queremos procesar.
  • 2: El valor del nuevo array a generar. Puede ser el índice de la columna a extraer datos, o un string con la clave o propiedad que queremos recuperar o NULL en caso de querer que nos devuelva el elemento entero del array.
  • 3: El índice del nuevo array a generar, puede ser nulo.Este valor podría ser la clave de tipo integer de la columna, o podría ser el nombre de la clave de tipo string.

A continuación os dejo el ejemplo del código equivalente al foreach superior.

<?php
$datos = [
    ['id' => 111, 'nombre' => 'nombre1', 'edad'=>1],
    ['id' => 112, 'nombre' => 'nombre2', 'edad'=>2],
    ['id' => 113, 'nombre' => 'nombre3', 'edad'=>3],
];

$resultado = array_column($datos, null, 'id');
print_r($resultado);
// Output
// Array
// (
//     [111] => Array
//         (
//             [id] => 111
//             [nombre] => nombre1
//             [edad] => 1
//         )
//     [112] => Array
//         (
//             [id] => 112
//             [nombre] => nombre2
//             [edad] => 2
//         )
//     [113] => Array
//         (
//             [id] => 113
//             [nombre] => nombre3
//             [edad] => 3
//         )
// )

Array_column también funciona para un array de objetos.

<?php
$dato1 = new stdClass;
$dato1->id = 1;
$dato1->nombre = "nombre1";
$dato2 = new stdClass;
$dato2->id = 2;
$dato2->nombre = "nombre2";
$datos = [$dato1, $dato2 ];

$resultado = array_column($datos, null, 'id');
print_r($resultado);
// Output
// Array
// (
//     [1] => stdClass Object
//         (
//             [id] => 1
//             [nombre] => nombre1
//         )
//     [2] => stdClass Object
//         (
//             [id] => 2
//             [nombre] => nombre2
//         )
// )

Otros ejemplos de uso de array_column

Hasta ahora los ejemplos han sido para devolver el objeto completo indexado. Y si ahora necesitamos solamente, una propiedad de los objetos. Vamos a suponer que solo necesitamos saber el id de los datos. En ese caso, sería aún más intuitivo.

<?php
$dato1 = new stdClass;
$dato1->id = 1;
$dato1->nombre = "nombre1";
$dato2 = new stdClass;
$dato2->id = 2;
$dato2->nombre = "nombre2";

$datos = [$dato1, $dato2];

$resultado = array_column($datos, 'id');
print_r($resultado);

// Output
// Array
// (
//     [0] => 1
//     [1] => 2
// )

O finalmente, otro uso, queremos un array donde el id sea la clave y el nombre el valor.

<?php
$dato1 = new stdClass;
$dato1->id = 1;
$dato1->nombre = "nombre1";
$dato2 = new stdClass;
$dato2->id = 2;
$dato2->nombre = "nombre2";

$datos = [$dato1, $dato2];

$resultado = array_column($datos, 'nombre', 'id');
print_r($resultado);

// Output
// Array
// (
//     [1] => nombre1
//     [2] => nombre2
// )

Filtrar datos usando array_filter

Usar array_filter es una buena práctica para hacer un filtro de datos. Un ejemplo va a ser el siguiente.

<?php
$excluded = [1,4];
$datos = [1,2,3,4,5];

// Filtrar con loops.
$result = [];
foreach ($datos as $key => $dato) {
  if (!in_array($dato, $excluded)) {
      $result[] = $dato;
  }
}
print_r($result);
// OUTPUT
// Array
// (
//     [0] => 2
//     [1] => 3
//     [2] => 5
// )

// Filtrar usando array_filter.
$non_excluded = array_filter($datos, function($dato) use ($excluded){
  return !in_array($dato, $excluded);
});
print_r($non_excluded);
// OUTPUT
// Array
// (
//     [0] => 2
//     [1] => 3
//     [2] => 5
// )

Vemos que ambos resultados son lo mismo. Pero en tema de legibilidad, limpieza y comprensión de código usar la función nativa es bastante más intuitivo.

Resumen

Bien, pues este ha sido otro post más. Espero seguir con esta constancia y seguir compartiendo información útil. El intentar hacer un código limpio y fácil de entender, es bueno tanto para nosotros, como para la mantenibilidad del proyecto.

Reducir complejidad y facilitar la capacidad de tests del proyecto, será siempre bueno a la larga. Y el desarrollo de código limpio, poniendo un poco de atención y refactorizando en la medida de lo posible nos hará cada vez más acostumbrados a usar buenas prácticas.

Esto ha sido todo por hoy.

Enlaces y referencias

https://es.wikipedia.org/wiki/Complejidad_ciclom%C3%A1tica

https://www.php.net/manual/es/function.array-column.php

https://www.php.net/manual/es/function.array-filter.php

Comparte 🙂

Si te ha gustado el contenido de este artículo no te olvides de compartirlo ya que con eso me harías muy feliz. GRACIAS 😉

Participa 😉

Además de todo ello, si tienes dudas o puedes aportar algo con un comentario, no dudes en hacerlo. GRACIAS 😉

¿Y tú qué opinas?

Antes de participar en los comentarios, ten en cuenta que leeré personalmente cualquier cosa que escribas. Así que, por favor, mantén las formas y compórtate como una persona de bien.

  • (will not be published)

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>