viernes, 4 de octubre de 2024

Funciones. Matrices.

Frecuencias

Una vez que ya sabemos [buscar elementos] en una matriz, estamos en disposición de desarrollar funciones para determinar el número de veces que se repite ese elemento o dato (su frecuencia) y la posición o posiciones que ocupa.


La función que nos permiten calcular la frecuencia de un dato en una matriz es, en realidad, una derivación de la función que nos permite comprobar su presencia en ella (bPos()), lo que no deja de ser la forma más simple de frecuencia (f=0 vs. f=1). Por ello nos basaremos en esa función para desarrollar la actual. Más compleja es la función que nos devuelva las posiciones que ese dato ocupa en la matriz, pero ya tendremos tiempo de hablar de ella.

Empecemos por la función que nos permite conocer el número de veces que un dato se presenta en una matriz que como ya dije y podemos comprobar, es similar (incluso más sencilla) a bPos(). 

Function fDato (ByRef a(), sDt As String) As Integer

Dim c As Integer, f As Integer

f = 0

For c = 0 To UBound(a())
If a(c) = sDt Then
f = f + 1
End If
Next

fDato = f

End Function

Vemos que recibe dos parámetros, la matriz de referencia (a()) y el dato a buscar (sDt), y devuelve un valor numérico. Además cuenta con dos variables privadas, un contador para recorrer la matriz-parámetro (c) y otro para acumular la repetición de la presencia del dato en ella (f).

El proceso que desarrolla es muy simple:
  • Recorre la matriz-parámetro hasta su último elemento mediante un bucle (For c = 0 To UBound(a()))
  • Y, mediante un condicional, busca las coincidencias que se encuentran en el contenido de la matriz valorando su igualdad con el dato de referencia (sDt) pasado como argumento (If a(c) = sDt Then).
Dado que hemos asignado el valor inicial f = 0 al contador de la frecuencia, si el dato buscado no se encuentra en la matriz, la función devolverá 0, que en este caso es un dato de frecuencia, no un índice de posición; pero si el dato sí se encuentra en la matriz se produce el incremento de f mediante la expresión subordinada (f = f + 1) al condicional. 

Este proceso se repite hasta finalizar el recorrido por la matriz-parámetro, finalizando la función con el Return correspondiente (fDato = f).

Para muchos análisis, esta función puede ser suficiente, pero podemos necesitar conocer el índice o posición que ocupa cada una de las repeticiones del dato dentro de la matriz. Para ello deberemos desarrollar una segunda función ( pDatos())

Function pDatos ( ByRef a(), sDt As String)

Dim mF () As Integer
Dim c As Integer, f As Integer, nV As Integer

f = fDato (a(), sDt)

If f >= 1 Then 
ReDim mF(f-1)
nV = 0
For c = 0 To UBound(a())
If a(c) = sDt Then
mF(nV) = c
nV = nV + 1
End If
Next
Else
ReDim mF(0)
mF(0) = -1
End If

pDatos = mF()


End Function

Esta segunda función recurre a la primera (fDato()) para establecer la dimensión de su matriz privada (auxiliar), por lo que en realidad es una función complementaria y, si se quiere, derivada de aquella.

Recibe los mismos parámetro que la primera (y de hecho se los pasa a su vez como parámetros a ésta) y devuelve una matriz con datos numéricos que representan las posiciones en que se sitúa el dato de referencia (sDt) que, junto con la matriz-base (a()) también recibe del script principal.

Como privadas precisa una matriz auxiliar (mF ()) y tres variables (Dim c As Integer, f As Integer, nV As Integer). La matriz auxiliar es el contenido de su Return y las variables son un contador para el bucle (c), una variable receptora del Return de la función fDato() (f) y una última variable (nV) como índice para recorrer su función auxiliar. Veremos su lógica en el análisis de la función, a continuación.

Lo primero que hacemos es solicitar la acción de la función fDato () cuyo Return asignamos a la variable f (f = fDato (a(), sDt)), el cual usamos para redimensionar su matriz auxiliar (ReDim mF(f-1)) (1).

Sobre esta base desarrollamos el proceso central de la función, que se estructura de la siguiente manera:

Mediante un condicional se controla el efecto de la presencia/ausencia del dato en la matriz-parámetro. En caso de que este dato esté presente en dicha matriz (If f >= 1 Then), se desarrolla el proceso que se explica a continuación. Pero en caso de que no lo esté se dimensiona la matriz auxiliar y se asigna como contenido y único el valor -1 (Else -> ReDim mF(0) -> mF(0) = -1) (2

Dentro de la primera parte del condicional anterior, mediante un bucle se recorre la matriz-parámetro (For c = 0 To UBound(a())) haciendo uso del contador c. Este bucle contiene a su vez un segundo condicional que analiza la presencia del dato-parámetro en la matriz-parámetro (If a(c) = sDt Then).

Cuando su resultado es True (3) se asigna a la posición nV de la matriz auxiliar el valor c en ese momento del ciclo (mF(nV) = c), generándose a continuación el incremento +1 de ese contador secundario nV (nV = nV + 1). Esto permite recorre la matriz secundaria, asignando a sus posiciones, y como datos, los valores posicionales del dato buscado en la matriz-parámetro (4).

Finaliza la función con su Return (pDatos = mF()), lo que implica que el script principal cuenta con información sobre las posiciones que el dato solicitado ocupa dentro de la matriz principal. En caso de que no exista este dato se devuelve una

NOTAS

(1) Obsérvese que la dimensión de esta matriz (mF()) viene determinada por el número de veces que la matriz-parámetro (a()) contiene el dato (resultado de la función fDato ()) menos 1 ((f-1)). Esto es debido, de nuevo, a que el primer valor de posición de una matriz es 0, por lo que el valor f implicaría sobredimensionar la matriz auxiliar, con el consiguiente fallo de funcionamiento de la misma.
(2) De este modo, el script principal recibe como Return una matriz de un único elemento que contiene un valor específico (-1) y puede procesar el resultado obtenido sin confusión en cuanto a su significado. Evitamos de paso que se produzca un error en el funcionamiento de la función.
(3) Esto es: cuando efectivamente en la posición c de la matriz-parámetro (a(c)) se encuentra el dato buscado(a (a(c) = sDt)
(4) La variable-contador secundario nV ha sido igualada a 0 con anterioridad al bucle (nV = 0) a fin de que el inicio del recorrido de las posiciones de la matriz auxiliar (mF(nV)) comience en esta posición con toda seguridad.

No hay comentarios:

Publicar un comentario

Comenta esta entrada