Introducción
A los arreglos podemos aplicarles búsquedas. No importa si es un arreglo de objetos, de números, de cadenas o de lo que sea, siempre se les podrá aplicar una búsqueda secuencial usando PHP.
Una búsqueda bastante popular (aunque no es la más óptima) es la búsqueda secuencial, en donde iteramos todo el arreglo comparando cada elemento con la búsqueda.
La velocidad de este algoritmo radica en la “suerte” que tengamos. Por ejemplo, si el elemento que buscamos está en la posición 2, sólo se habrán hecho 3 iteraciones (porque comienzan en 0); en cambio, si está en la posición 100000 se habrán hecho 100001.
Hay otros algoritmos, pero hoy veremos el de la búsqueda secuencial que es muy simple.
Búsqueda secuencial en arreglo de PHP
Métodos nativos
PHP proporciona métodos nativos. Tranquilo, si vienes por el algoritmo está más abajo, pero puede que hayas venido para ver la forma más óptima de buscar el índice del elemento en un arreglo.
Este lenguaje proporciona el método array_search que busca un valor en un arreglo. Esto es útil cuando tenemos datos simples como enteros o cadenas, no funcionará con objetos que tengan propiedades.
Veamos este ejemplo en donde definimos un simple arreglo:
<?php
$mascotas = ["Maggie", "Petra", "Misifú"];
$busqueda = "Maggie";
$indice = array_search($busqueda, $mascotas);
echo "La mascota $busqueda está en el índice $indice";
?>
Ahí dirá que está en el índice 0. Si buscamos algo que no existe, devolverá false. Es importante comparar con el operador de identidad ===
.
Por ejemplo, en este caso $indice
será false
:
<?php
$mascotas = ["Maggie", "Petra", "Misifú"];
$busqueda = "Cuco";
$indice = array_search($busqueda, $mascotas);
echo "La mascota $busqueda está en el índice $indice";
?>
Entonces para comparar si existe o no, primero comprobamos si el valor es false
. En caso de que sea false
, significa que el elemento no está presente en el arreglo. Si es un número, entonces es el índice.
Búsqueda estricta con array_search
Sabemos que PHP es un lenguaje de tipado débil, por eso el tercer parámetro de esta función es un booleano indicando si queremos que la comparación se haga con ===
o con ==
. Recomiendo ponerlo como true
para que se haga con el operador de identidad ===
.
Por dar un ejemplo, se haría así:
<?php
$mascotas = ["Maggie", "Petra", "Misifú"];
$busqueda = "Maggie";
$indice = array_search($busqueda, $mascotas, true);
echo "La mascota $busqueda está en el índice $indice";
?>
Si lo ponemos como false
o no lo ponemos, y hay un arreglo de números mezclados con cadena puede que busquemos la cadena 0″ pero si lo comparamos con el entero 0 usando ==
devolverá true
, dándonos resultados equivocados.
Métodos hechos por nosotros
Si queremos hacerlo manualmente, ya sea porque queremos implementar el algoritmo o porque queremos una búsqueda personalizada, aquí está el código necesario. Este método nos da más control sobre lo que hacemos.
Recomiendo encerrar todo esto dentro de una función que se parezca a array_search; es decir, que reciba un arreglo por referencia, así como una búsqueda y devuelva el índice o -1 (no false) en caso de no encontrar nada.
Para un arreglo de enteros (el más básico) sería así:
<?php
function busquedaSecuencialEnArregloDeEnteros(&$arreglo, $numeroBuscado){
foreach($arreglo as $indice => $numero){
/*
Recorrer todo el arreglo e ir comparando elemento por elemento.
Si lo encontramos, el foreach se detiene y se regresa el índice
*/
if($numero === $numeroBuscado){
return $indice;
}
}
/*
Si después de recorrer todo el arreglo no lo encontramos,
entonces devolvemos -1
*/
return -1;
}
Aquí un ejemplo de su llamada:
<?php
/*
Probar
*/
$numeros = [1, 50, 22, 50, 80, 5164, 5151, 441, 294, 36, 21];
$busqueda = 441;
$indice = busquedaSecuencialEnArregloDeEnteros($numeros, $busqueda);
echo "El número $busqueda está en la posición $indice";
La salida es: El número 441 está en la posición 7
Lo mismo podríamos hacer con cadenas, y al hacerlo de esta manera podemos ignorar mayúsculas o hacer cosas más interesantes.
Búsqueda secuencial con objetos
Como lo dije, array_search no provee un método para comparar objetos. Por ejemplo, supongamos que tenemos un carrito de compras que tiene objetos de la clase Producto.
Para simplificar, un producto únicamente tiene código de barras, precio y descripción. La clase queda así:
<?php
class Producto{
private $codigo;
private $descripcion;
private $precio;
public function __construct($codigo, $descripcion, $precio){
$this->codigo = $codigo;
$this->descripcion = $descripcion;
$this->precio = $precio;
}
public function getCodigo(){
return $this->codigo;
}
}
Es para ejemplificar, no lo olvides. Luego podemos tener un arreglo como este:
<?php
$productos = [
new Producto("123", "Nugs Recreo", 11),
new Producto("281196", "Nito bebible", 15),
new Producto("800", "Detergente", 20),
];
La función para hacer una búsqueda secuencial en un arreglo de objetos (en este caso de productos) es esta:
<?php
function busquedaSecuencialEnArregloDeObjetos(&$arreglo, $codigoDeBarrasBuscado){
foreach($arreglo as $indice => $producto){
/*
Recorrer todo el arreglo e ir comparando elemento por elemento.
Si lo encontramos, el foreach se detiene y se regresa el índice
*/
if($producto->getCodigo() === $codigoDeBarrasBuscado){
return $indice;
}
}
/*
Si después de recorrer todo el arreglo no lo encontramos,
entonces devolvemos -1
*/
return -1;
}
Es exactamente lo mismo que el ejemplo de arriba, sólo que como ahora trabajamos con objetos tenemos que acceder a sus propiedades y compararlas.
Si necesitas comparar otra propiedad, la comparas y ya. O puedes comparar dos al mismo tiempo; incluso puedes compararlas a todas.