Filtrar una lista de modo que sólo quede una copia de cada elemento sin repetición... (este o algo parecido es la idea que debería ser el título del mensaje).
Sea una lista de elementos (en el ejemplo consideramos números y más concretamente usaremos byte), dicha lista contiene una cantidad arbitraria de elementos, se desea obtener una lista que incluya única copia de cada eleemnto.
Para crear elcódigo y una demostración visual, vamos a necesitar 2 listbox y 2 botones.
* El lis1 contendrá un volcado con la lista de elementos original,
* El lis2 tendrá un volcado cion la lista de elementos ya filtrados.
* El btn1 crea una lista de elementos aleatoria (nos aseguramos que existan repetidos) y presenta la listas en lis1
* El btn2 lama a la función que filtra la lista y presenta el resultado en el lis2
Código previo:
' nótese la declaración de la matriz a nivel de formulario...
Dim ElemOrig(0 To 9999) As Byte
Private Sub Form_Load()
' queremos usar el generador aleatorio de números, implantamos una semilla diferente en cada uso.
Randomize Timer
End Sub
Código del boton 1:
* El btn1 crea una lista de elementos aleatoria (nos aseguramos que existan repetidos) y presenta la listas en lis1
Private Sub Btn1_Click()
Dim k As Integer
Lis1.Clear ' vaciamos elcontenido actual
' un byte tiene un valor cuyo rango oscila entre 0 y 255, si proveemos más de 256 valores
' tenemos la certeza de que habrá repetidos.
' usamos 10.000 elemntos debe haber alrededor de 40 repeticiones de cada elemento
For k = 0 To 9999
ElemOrig(k) = Int((255 + 1) * Rnd)
Lis1.AddItem (ElemOrig(k))
Next
End Sub
Debe notarse que el generador aleatorio, porporciona realmente valores pseudo-aleatorios.
Código del botón 2: * El btn2 lama a la función que filtra la lista y presenta el resultado en el lis2
Private Sub Btn2_Click()
Dim k As Integer, n As Integer
Dim ElemFil() As Byte
' vaciamos elcontenido previo
Lis2.Clear
' ejecutamos el filtrado
ElemFil = FiltrarUnicos(n)
' volcamos la matriz obtenida en el listbox
For k = 0 To n - 1
Lis2.AddItem (ElemFil(k))
Next
Erase ElemFil ' liberamos memoria ...
' indicamos cuantos elementos únicos se ha hallado.
MsgBox "se han encontrado " & n & " elementos únicos sonre los 10.000 originales."
End Sub
Código de la función que realiza el filtrado.
' devuelve el número de elementos únicos
Private Function FiltrarUnicos(ByRef n As Integer) As Byte()
Dim k As Integer
Dim ls() As Integer
Dim ElemFil() As Byte
' Hacemos que la lista de devolución tenga el mismo tamaño que la original
ReDim ls(0 To 9999)
ReDim ElemFil(0 To 999)
' vamos recreando en una lista intermedia, la cantidad de apariciones de cada elemento
For k = 0 To 9999
ls(ElemOrig(k)) = ls(ElemOrig(k)) + 1
Next
' si la lista intermedia tiene un valor mayor que 0 ese elemnto existe en la lista original, lo tomamos
For k = 0 To 9999
If ls(k) > 0 Then
ElemFil(n) = k
n = n + 1
End If
Next
Erase ls
' la lista definitiva, tiene espacio no usado lo retiramos
ReDim Preserve ElemFil(0 To n - 1)
' devolvemos la lista filtrada ordenada de menor a mayor.
FiltrarUnicos = ElemFil
Erase ElemFil
End Function
Como verás sólo podrás aplicarlo a tu código si logras entenderlo y por tanto sabes como implementarlo... esto es, no te voy a dar el código exacto a tu problema, el objetivo es que aprendas para resolver por tí mismo los problemas que se presenten no resolver un problema puntual a base copiar y pegar.
Esta solución tiene algunos inconvenientes que detallo.
Utiliza memoria adicional por loque si una lista tiene pongamos 100 millones de elementos puede suponer un gran consumo de memoria en el equipo. Debe tenerse en cuenta...
No vale para casos donde los elementos tienen valores decimales (se puede modificar para lograr que valga, pero la memoria a usar se dispara * 10 por cada decimal usado, es decir si tienes una matriz de 10.000 elementos la matriz intermedia para 4 decimales (por ejemplo un tipo de datos currency) usaría 10.000 * (10^4) elemntos es decir : 10.000.000 (10 millones). Este valor se duplica por que la matriz de salida inicalmente debe contemplar el mismo número de elemtnos que la matriz intermedia.
En definitiva sólo es útil para números enteros y atendiendo al tamaño de la matriz para vigilar la memoria usada. Tiene a favor que es el más rápido.
Este algoritmo es una implementación del algoritmo conocido como 'counting', que se utiliza para ordenar números (que tiene las mismas limitaciones descritas), sólo que en este caso hay una modificación dirigida a filtrar elementos repetidos.