Hola, a los visitantes.
Me encontré con un problema (serio, para mi), que consistía en buscar varios valores en un array.
En mi caso estaba buscando unos 6.000 valores en un array de 30.000 elementos.
La solución inicial utilizar AScan, bueno, esto MATABA la máquina LITERALMENTE.
Pensé, bueno en vez de recorrer 6.000 veces el array de 30.000 voy a recorrer UNA vez el array de
30.000 buscando los 6.000. El resultado mejoro, pero no demasiado.
Pensando me acordé de las búsquedas binarias, me dí unas vueltas por internet y al final hice esto:
// ============================================================================
// ABinarySearch( aList, xSearch, nCol )
// 04/04/2015 21:52:26 Creación. Hace una búsqueda binaria en un array.
// ============================================================================
FUNCTION ABinarySearch( aList, xSearch, nCol )
LOCAL nFirst, nLast, nPos, nResult AS NUMBER
LOCAL xItem AS ANY
SetDefaultNumeric( nCol, 0 )
nResult := 0
nFirst := 1
nLast := Len( aList )
WHILE ( nFirst <= nLast )
nPos := Int( ( nFirst + nLast ) / 2 )
xItem := If( nCol > 0, aList[ nPos, nCol ], aList[ nPos ] )
IF xItem == xSearch
nResult := nPos
EXIT
/**
* Si el valor del item de la mitad es mayor que el elemento buscado
* seleccionamos la primera mitad.
*/
ELSEIF xItem > xSearch
nLast := nPos - 1
/**
* Seleccionamos la segunda mitad.
*/
ELSE
nFirst := nPos + 1
ENDIF
END WHILE
RETURN nResult
Los tiempos ahora SON DE UN PAR DE SEGUNDOS, cuando antes el equipo hasta ponía "no responde".
Solo tiene "UN INCONVENIENTE" que el array donde se hace la búsqueda tiene que estar ordenado con
algo como esto:
ASort( aItems,,, { |x, y| x[ D06_ART_ID ] < y[ D06_ART_ID ] } )
Pero con todo y con eso la búsqueda es SUPER RÁPIDA.
Si decidís utilizarla tenéis que pedirme la licencia de uso que es por equipo y minutos de uso y viene
incorporada en el código una protección por KEY con encripitación de 48.000 bytes