Uso de cookies

Utilizamos cookies propias y de terceros para mejorar nuestros servicios y mostrarle publicidad relacionada con sus preferencias mediante el análisis de sus hábitos de navegación. Si continúa navegando, consideramos que acepta su uso. Para obtener más información o bien conocer cómo cambiar la configuración lea nuestra Política de cookies

Funciones para manejo de matrices

El uso de las matrices (arrays) en Basic puede facilitarnos mucho las tareas de programación de macros. Usar una colección adecuada de funciones puede ahorrarnos muchas líneas de escritura y simplificar la lectura, análisis y depuración de nuestros programas.

A continuación mostramos algunas de estas funciones. No son todas las necesarias, ni pretenden ser perfectas. Como siempre ocurre cuando hablamos de programación, todo es mejorable.

Si consideras que tu función es más adecuada no dudes en mandarnos un correo con ella y la integraremos en este artículo.

Comentarios del código

En todas las funciones se ha agregado ByRef o ByVal definiendo el sistema de pasar el argumento según se ha considerado necesario para un adecuado funcionamiento.

Por defecto OOo Basic considera que los argumentos se pasan siempre por referencia; por lo tanto, y aunque es innecesario, se ha agregado ByRef para mejorar la lectura y comprensión de la función.

Las variables que se han utilizado en las funciones se han nombrado siguiendo el siguiente esquema:

  • u para almacenar el ordinal del último elemento de la matriz devuelto por la función uBound.
  • l para almacenar el ordinal del primer elemento de la matriz devuelto por la función lBound, dado que puede ser 0 (por defecto) o 1 según se haya establecido el parámetro Option Base.
  • a para el array a().

Añadir un nuevo elemento a un array

La función aAdd nos permite agregar un nuevo elemento al final de una matriz.

Function aAdd( ByRef a(), ByVal xValor )
'--------------------------------------------------------------------------------------------
   ' Agrega un elemento a un array y lo llena con xValor
   ' se puede llamar como función [ a = aadd( a, "5") ] o como subrutina  [ aadd a, "5" ]
   Dim u As Long
   u = UBound( a ) + 1
   ReDim Preserve a( u )
   a(u) = xValor
   aAdd = a
End Function

Dado que la matriz se pasa por referencia, podemos utilizarla como subrutina o como función:

' Como subrutina
aAdd miArray, 1000
 
' Como función
miArray = aAdd(  miArray, 1000 )

Eliminar un elemento o rango de elementos de un array

La función aDel nos permite eliminar un elemento o rango de elementos de una matriz. Los argumentos nIni y nFin tienen la siguiente operativa:

  • nIni: Si es -1 indica que se pretende eliminar el último elemento de la matriz. Cualquier otro valor indica el elemento que se desea eliminar en la matriz. Si se utiliza junto con nFin indicará cual es el primer elemento del rango de elementos a eliminar en la matriz.
  • nFin: Su uso es opcional. Indica el último elemento del rango de elementos a eliminar en la matriz.
Function aDel( ByRef a(), nIni As Long, Optional nFin As Long )
'--------------------------------------------------------------------------------------------
   ' Elimina elementos de un array
   ' se puede llamar como función [ a = aDel( a, 5) ] o como subrutina  [ aDel a, 5 ]
   ' si nIni es -1 se eliminará el último elemento
   Dim aTmp(), u As Long, r As Long, n As Long
   If IsMissing( nFin ) Then nFin = nIni
   On Local Error GoTo error_aDel
   u = UBound(a())
   If nIni = -1 Then        ' clave especial, borrar el último elemento
      ReDim aTmp(u-1)
      For n=0 To u-1
         aTmp(n)=a(n)
      Next
   Else
      ReDim aTmp(u-(nFin-nIni)-1)
      For n=0 To nIni-1
         aTmp(n)=a(n)
      Next
      r=n
      For n=nFin+1 To u
         aTmp(r)=a(n)
         r=r+1
      Next
   End If
   a() = aTmp()
   aDel = a()
   Exit Function
   error_aDel:    ' sólo tiene un elemento o no se ha inicializado el array
   ReDim a()
   aDel = a()
End Function

Dado que la matriz se pasa por referencia, podemos utilizarla como subrutina o como función:

' Como subrutina
aDel miArray, 3
 
'Como función:
miArray = aDel(  miArray, 3 )

Se ha utilizado el sistema de control de error para dos supuestos: se intenta eliminar el último elemento del array o éste no tiene elementos; en ambos casos devuelve un array vacío sin elementos.

No hemos utilizado Redim Preserve para reducir el tamaño de la matriz cuando se trata de eliminar el último elemento porque extrañamente no "preserva" el contenido.

Buscar un dato en un array unidimensional

La función aSeek nos permite encontrar la posición que ocupa un dato en una matriz. Opcionalmente se le puede indicar desde que elemento desea que se inicie la búsqueda.

Function aSeek( ByRef a(), xValor, Optional nIni ) As Long
'--------------------------------------------------------------------------------------------
   ' Busca en un array unidimensional. nIni indica desde qué posición se inicia la búsqueda
   Dim n As Long, l As Long, u As Long
   l = LBound( a )
   u = UBound( a )
   If Not IsMissing( nIni ) Then l = nIni
   For n=l To u
      If a(n) = xValor Then Exit For
   Next n
   If n > u Then n = -1 ' no se ha encontrado
   aSeek = n
End Function

Buscar un dato en un array bidimensional

La función aSeekMD nos permite encontrar la posición que ocupa un dato en la dimensión x una matriz de y dimensiones. Opcionalmente se le puede indicar desde que elemento desea que se inicie la búsqueda.

Function aSeekMD( ByRef a(), nDimension As Long, xValor, Optional nIni ) As Long
'--------------------------------------------------------------------------------------------
   ' Busca en la dimensión nDimension de un array multidimensional.
   ' nIni indica desde qué posición se inicia la búsqueda
   Dim n As Long, l As Long, u As Long
   l = LBound( a, nDimension )
   u = UBound( a, nDimension )
   If Not IsMissing( nIni ) Then l = nIni
   For n=l To u
      If a(nDimension,n) = xValor Then Exit For
   Next n
   If n > u Then n = -1 ' no se ha encontrado
   aSeekMD = n
End Function

Puedes probar con este ejemplo:

   Dim a(3,2)
   For n=0 To 3
      For m=0 To 2
         j=j+1
         a(n,m)=j
      Next
   Next
   MsgBox aSeekMD( a, 2, 9 ) ' devuelve 2

Recordemos que la notación de matrices multidimensionales es:

Basic Funciones Arrays 001.png

Buscar un dato en un array que contiene arrays

La función aSeekMArray nos permite encontrar la posición que ocupa un dato en una matriz que está embebida en un elemento de otro array. Opcionalmente se le puede indicar desde que elemento desea que se inicie la búsqueda.

Es parecido a utilizar arrays multidimensionales, pero la notación es diferente.

Function aSeekMArray( ByRef a(), nDimension As Long, xValor, Optional nIni ) As Long
'--------------------------------------------------------------------------------------------
   ' Busca en la dimensión nDimension de un array multidimensional.
   ' nIni indica desde qué posición se inicia la búsqueda
   Dim n As Long, l As Long, u As Long
   l = LBound( a(nDimension) )
   u = UBound( a(nDimension) )
   If Not IsMissing( nIni ) Then l = nIni
   For n=l To u
      If a(nDimension)(n) = xValor Then Exit For
   Next n
   If n > u Then n = -1 ' no se ha encontrado
   aSeekMArray = n
End Function

Puedes probar con este ejemplo:

   Dim a()
   a = Split("1,2,3;4,5,6;7,8,9;10,11,12", ";")
   For n=0 To 3
      a(n) = Split(b(n),",")
   Next
   MsgBox aSeekMArray( a, 2, "8") ' devuelve 1

Indicar que buscar el valor de texto "8" en lugar del valor numérico 8 es debido a cómo hemos contruido las matrices de la prueba.

Recordemos que la notación de matrices contenidas en otras matrices es:

Basic Funciones Arrays 002.png

Eliminar los elementos vacíos de un array

La función aRemoveEmpty nos permite eliminar los elementos vacíos de una matriz.

Function aRemoveEmpty ( ByRef a() )
'--------------------------------------------------------------------------------------------
   ' elimina los elementos vacíos de un array
   ' se puede llamar como función o como subrutina
   Dim n As Long, u As Long, l As Long
   u = UBound( a )
   l = LBound( a )
   For n = u To l Step -1
      If Trim(a(n))= "" Then a = aDel( a, n )
   Next
   aRemoveEmpty = a
End Function

Dado que la matriz se pasa por referencia, podemos utilizarla como función o como subrutina:

' Como subrutina
aRemoveEmpty miArray
 
' Como función
miArray = aRemoveEmpty( miArray )

Eliminar elementos duplicados en un array

La función aRemoveDuplicates elimina los elementos repetidos en una matriz.

Function aRemoveDuplicates ( ByRef a() )
'--------------------------------------------------------------------------------------------
   ' elimina los elementos duplicados de un array
   ' se puede llamar como función o como subrutina
   Dim n As Long, u As Long, l As Long
   u = UBound( a )
   l = LBound( a )
   Do While True
      For n = l+1 To u
         If a(n) = a(l) Then
            a = aDel( a, n )
            u = u-1
            l = l-1
         EndIf
      Next
      l = l+1
      If l > u Then Exit Do
   Loop
   aRemoveDuplicates = a
End Function

Dado que la matriz se pasa por referencia, podemos utilizarla como función o como subrutina:

' Como subrutina
aRemoveDuplicates miArray
 
' Como función
miArray = aRemoveDuplicates( miArray )

Rellena todos los elementos de un array

La función aFill nos permite rellenar todos los elementos de una matriz con el dato pasado.

Function aFill( ByRef a(), ByVal xValor)
'--------------------------------------------------------------------------------------------
   ' llena el array con xValor por valor, no por referencia
   ' se puede llamar como función o como subrutina
   Dim n As Integer
   For n = LBound(a) To UBound(a)
      a(n) = xValor
   Next
   aFill = a
End Function

Al pasar el dato por valor garantizamos la independencia de los elementos de la matriz de las variables o campos con los que se rellene.

Dado que la matriz se pasa por referencia, podemos utilizarla como función o como subrutina:

' Como subrutina
aFill miArray, "Hola"
 
' Como función
miArray = aFill( miArray, "Hola" )

Ordenar un array unidimensional

La subrutina aSort nos permite ordenar de forma ascendente una matriz unidimensional. Opcionalmente se le puede indicar un rango de elementos a ordenar, dejando en este caso el resto sin ordenar.

Sub aSort( ByRef a(), Optional nPri, Optional nUlt)
'--------------------------------------------------------------------------------------------
   ' ordena un array unidimensional en orden ascendente
   ' opcional ordenar parcialmente el array
   Dim nIndi As Integer, nUindi As Integer, n As Integer
   Dim x, nCentro
 
   If IsMissing(nPri) Then nPri = 0
   If IsMissing(nUlt) Then nUlt = UBound(a)
 
   nIndi = nPri
   nUindi = nUlt
 
   n = Int((nIndi + 1 + nUindi) / 2)
   nCentro = a(n)
 
   Do Until nIndi > nUindi
      Do While a(nIndi) < nCentro
         nIndi = nIndi + 1
      Loop
      Do While a(nUindi) > nCentro
         nUindi = nUindi - 1
      Loop
      If nIndi <= nUindi Then
         x = a(nIndi)
         a(nIndi) = a(nUindi)
         a(nUindi) = x
         nIndi = nIndi + 1
         nUindi = nUindi - 1
      End If
   Loop
 
   If nPri < nUindi Then
      aSort a, nPri, nUindi
   End If
 
   If nUlt > nIndi Then
      aSort a, nIndi, nUlt
   End If
 
End Sub

Ejemplo de uso

   Dim a()
   a = Split( "3,2,1,0,9,8,7,6,5,4", ",")
   aSort a
   MsgBox Join(a, ",")  ' resultado "0,1,2,3,4,5,6,7,8,9"
 
   a = Split( "3,2,1,0,9,8,7,6,5,4", ",")
   aSort a, 3
   MsgBox Join(a, ",")  ' resultado "3,2,1,0,4,5,6,7,8,9"
 
   a = Split( "3,2,1,0,9,8,7,6,5,4", ",")
   aSort a, 3, 7
   MsgBox Join(a, ",")  ' resultado "3,2,1,0,6,7,8,9,5,4"

Clonar un array

La función aClone nos permite crear un duplicado de un array.

Function aClone( a() )
'--------------------------------------------------------------------------------------------
   ' crea un duplicado del array pasado
   Dim l As Long, u As Long, n As Long, x()
   l = LBound( a )
   u = UBound( a )
   ReDim x(u)
   For n=l To u: x(n) = a(n) : Next
      aClone = x()
End Function

La copia creada es independiente del array original, como demuestra el siguiente código.

   Dim a() As String, b() As Long
   a = Array(4,3,2,1)
   b = aClone(a)
   MsgBox Join(a, ",") & "  /  " & Join(b,",") ' obtenemos 4,3,2,1  / 4,3,2,1
   asort a
   MsgBox Join(a, ",") & "  /  " & Join(b,",") ' obtenemos 1,2,3,4  / 4,3,2,1

Obtener el último elemento de un array

La función aTail devuelve el último elemento de una matriz.

Function aTail( a() )
'--------------------------------------------------------------------------------------------
   ' devuelve el último elemento de un array
   aTail = a( UBound(a) )
End Function

Evaluar si un array está vacío

La función aIsEmpty devuelve VERDADERO si el array está vacío.

Function aIsEmpty( a() ) As Boolean
'--------------------------------------------------------------------------------------------
   ' devuelve true si el array está vacío
   On Local Error GoTo Error_aVacio
   aIsEmpty = UBound(a)
   Exit Function
Error_aVacio:
   On Error GoTo 0
   aIsEmpty = True
End Function
Modificada el 30 ago 2015 03:53.   Visitas: 14 018