Algoritmo de consulta utilizando un arreglo prioritario y sin tener en cuenta las condiciones.
Estoy enfrentando este problema en la logística de mi empresa:
Dado un arreglo de valores mixtos:
arr = [
v1 => a,
v2 => b,
v3 => c,
v4 => d
]
ordenado por prioridad ASC (v1 es más importante que v2, … etc)
Necesito buscar valores en una tabla t de la siguiente manera:
select * from t where
... Y
t.v1 = a Y
t.v2 = b Y
t.v3 = c Y
t.v4 = d
Los 3 puntos en la consulta son las condiciones fijas.
Si no puedo encontrar ningún valor en la consulta, realizar la misma consulta ignorando el valor menos importante del arreglo:
select * from t where
... Y
t.v1 = a Y
t.v2 = b Y
t.v3 = c
Nuevamente, si no se encuentra el valor, realizar una consulta ignorando el siguiente valor menos importante:
select * from t where
... Y
t.v1 = a Y
t.v2 = b Y
t.v4 = d
La consulta puede ignorar todos los elementos del arreglo como en la última consulta:
select * from t where ...
Repetir esto hasta encontrar al menos 1 resultado de consulta o si todos los elementos del arreglo son nulos y no se encontró ningún resultado (devolver falso).
He diseñado mi algoritmo de búsqueda utilizando números binarios para encontrar el valor que funciona de la siguiente manera:
binaryValue = (2 ^ arr.lenght) - 1 //(En este caso: 2^4-1 = 15)
convertir el número binario 15 en un arreglo de booleanos “exploded” = [1, 1, 1, 1] (15 en binario es 1111)
Luego realizar la consulta considerando la posición 0 del arreglo booleanArray “exploded”: si es verdadero, considerar el valor en el arreglo de valores mixtos “arr” y así sucesivamente.
Hacer un bucle desde 15 hasta 0 (la iteración 0 es cuando el arreglo booleano es [0,0,0,0] y se ignoran todos los casos). La secuencia será la siguiente con esta lógica:
[a, b, c, d] // [1,1,1,1] = 15 (select * from t where ... and v1=a and v2=b and v3=c and v4=d)
[a, b, c] // [1,1,1,0] = 14 (select * from t where ... and v1=a and v2=b and v3=c)
[a, b, d] // [1,1,0,1] = 13 (select * from t where ... and v1=a and v2=b and v4=d)
...
[] // [0,0,0,0] = 0 (select * from t where ...)
El algoritmo de búsqueda funciona correctamente, pero tengo un gran problema de rendimiento.
El número de consultas realizadas en esta búsqueda es arr.length! (factorial). Por lo tanto, cuando el arreglo tiene longitud 4, el peor escenario realiza 24 consultas.
Si la longitud de arr es 6 (que es la longitud con la que estoy lidiando actualmente en mi código en producción), el peor caso realiza 720 consultas, lo cual es inaceptable.
Necesito encontrar una forma de mejorar esta búsqueda. ¿Alguien puede ayudarme?
Gracias de antemano.
davy.ai
Mejorado Algoritmo de Búsqueda para un Array de Valores Mixtos
Como experto en TI especializado en SQL, algoritmos, rendimiento, búsqueda y lógica, aquí está mi recomendación para mejorar el algoritmo de búsqueda para el array de valores mixtos.
El actual algoritmo de búsqueda realiza arr.length! consultas, lo cual no es escalable para arrays con un gran número de elementos. En cambio, podemos utilizar una estrategia de dividir y conquistar para reducir el número de consultas y mejorar el rendimiento.
Aquí está el algoritmo revisado:
Inicializar una variable
resultado
comonull
. Esta variable contendrá el resultado final de la búsqueda.Crear un nuevo array
queryArr
para guardar la consulta de búsqueda. Inicializarlo como[...condicionesFijas]
, dondecondicionesFijas
son las condiciones fijas en la consulta.Crear una nueva variable
índice
e inicializarla en 0. Esta variable se utilizará para llevar un registro de la posición actual enqueryArr
.Mientras
resultado
siga siendonull
yíndice
sea menor quearr.length
:Construir la consulta de búsqueda utilizando el actual
queryArr
:select * from t where ... and queryArr[0] and queryArr[1] and ... and queryArr[índice]
.Ejecutar la consulta de búsqueda y almacenar el resultado en
resultado
. Si hay un resultado, devolverlo.Si
resultado
sigue siendonull
, eliminar el último elemento dequeryArr
e incrementaríndice
.índice
es igual aarr.length
, devolverfalse
.Al ordenar el array de valores mixtos en orden descendente de prioridad y utilizar una estrategia de dividir y conquistar, podemos reducir significativamente el número de consultas y mejorar el rendimiento.
¡Espero que esto sea de ayuda! Avíseme si tiene alguna pregunta o necesita más asistencia.