logo

buscar en colecciones genericas

SergioT posted on Thursday, June 05, 2008 12:24 PM

Hola

tengo una clase cPersona que tiene 2 propiedades nombre y telefonos y luego
armo una coleccion generica con ella

dim l as new list( of cPersona)

una vez que inclui 50 objetos a la coleccion, dado un telefono necesito
buscar en la colección haber si existe, como hago para buscar en la
colección, se que hay que implmentar algo con el metodo Find de la colección
pero no encuentro elemplos de eso, por que la manera "primitiva" seria hacer
un for each y buscar con un If dentro del for each elemento a elemento pero
la verdad pienso que deben haber mejores maneras

gracias por la ayuda
sergio

buscar en colecciones genericas

grupo_noticia posted on Friday, June 06, 2008 11:34 AM

Por si no lo sabes, te comento que el método «Find» también hace
internamente una especie de «For Each» para encontrar el elemento
especificado; una vez que lo encuentra, abandono el bucle «For Each» para
devolver el objeto encontrado. Por tanto, creo que da igual que utilices el
método «Find» o un bucle «For Each».

Pero centrándonos en el asunto de tu mensaje, para que puedas utilizar el
método «Find» de un objeto «List Of (T)», deberás implementar una función
que tenga la misma firma del delegado «Predicate(Of T)», el cual se
encuentra declarado de la siguiente manera:

Public Delegate Function Predicate(Of T)(ByVal obj As T) As Boolean

Siendo así, bien podrías construir en el código cliente la siguiente
función:

Private Function BuscarPersona(ByVal persona As CPersona) As Boolean

If persona._nombre.ToLower = _nombre.ToLower Then
Return True
Else
Return False
End If

End Function

Pero para que el ejemplo funcione, tienes que declarar a nivel del
formulario un campo que contenga el nombre de la persona que se desea buscar
dentro de la colección:

Private _nombre As String

Como podrás observar, la función sólo se limita a buscar dentro de la
colección el nombre especificado en el campo «_nombre». Para ello
ejecutaríamos lo siguiente:

' Declaramos la correspondiente variable List (Of T)
'
Dim l As New List(Of CPersona)

' Añadimos unos cuantos elementos a la colección
'
With l
.Add(New CPersona("José,", "123456789"))
.Add(New CPersona("Roberto", "58974789"))
.Add(New CPersona("Rosario", "14589"))
.Add(New CPersona("Fernando", "56699885"))
.Add(New CPersona("Luis", "112523365"))
End With

' Creamos un objeto Predicate que apuntará a la función BuscarPersona
' Aquí está la cuestión de todo el tema.
'
Dim match As New Predicate(Of CPersona)(AddressOf BuscarPersona)

' Indicamos el nombre que deseamos buscar
'
_nombre = "RoBeRtO"

' Efectuamos la búsqueda
'
Dim p As CPersona = l.Find(match)

' Comprobamos el resultado
'
If p IsNot Nothing Then
MessageBox.Show("Encontrado: " & p._telefono)
Else
MessageBox.Show("Elemento no encontrado")
End If

Como bien podrás entender, se trata de un simple ejemplo que demuestra cómo
utilizar el método «Find» del objeto «List (Of T)»; de tí depende el
modificarlo para que se adapte a tus necesidades.

Pero vuelvo a insistir en lo dicho al principio; que para hacer lo mismo,
también puedes utilizar un bucle «For Each», porque el propio método «Find»
se encarga de recorrer todos los elementos de la colección hasta encontrar
el primero que cumpla con la condición especificada, que será el objeto que
devolverá la función, en el ejemplo, cualquier objeto CPersona cuyo nombre
sea «Roberto».

--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.

Hola EnriqueMuchas gracias por la aclaración, la verdad no sabia que el método

SergioT posted on Friday, June 06, 2008 3:08 PM

Hola Enrique

Muchas gracias por la aclaración, la verdad no sabia que el método find
funcionaba como un foreach, si es así la verdad no vale la pena el esfuerzo
es mas fácil hacer un for each directo y tradicional en el formulario y
listo, por lo menos en mi caso, probablemente la implementación del método
find sirva para otro tipo de problemas.

Como le comente al otro  amigo Ivan, como respuesta a su post, cambié la
implementación de List(of T) por un SortedList(Of String, CPersona) ,
supongo que esta es una opción mucho mejor y la verdad mas fácil y directa
de ordenar y buscar en una colección, tu que opinas de los SortedList ?

Hasta pronto y muchas gracias por tu explicación

Salu2
SergioT

buscar en colecciones genericas

grupo_noticia posted on Saturday, June 07, 2008 3:30 AM

Yo, respecto de la clase no genérica «SortedList», siempre he entendido que
se trata del objeto de tipo de colección más potente y flexible de los
existentes, pero a costa de pagar un alto precio en cuanto a rendimiento,
por lo que se aconseja utilizarlo cuando no haya otra solución menos costosa
en lo que se refiere a recursos utilizados. La clase genérica
SortedList(TKey, TValue) no la he utilizado, pero consultando la ayuda de
Visual Studio, también representa una colección de pares clave/valor que se
ordenan conforme a la clave basándose en la implementación de IComparer(T)
asociada, por lo que me imagino, aunque no te lo puedo confirmar, que su
utilización también sea costosa en términos de rendimiento.

Debido a la cantidad de objetos tipo de colección existentes en .net, una
veces será factible utilizar un tipo de objeto y otras veces no lo será
tanto, porque todo dependerá de la lógica del programa. No tienes más que
echarle un vistazo al siguiente tema de la ayuda de Visual Studio:

Tipos de colección utilizados normalmente

De todas maneras, y ya que vas a utilizar un tipo de colección, yo veo más
factible realizarlo con el método «Find» del objeto «List(Of T)» que
mediante el método «TryGetValue» del objeto SortedList(Of T, Value). Al
primero tendrás que pasarle un predicado para realizar la búsqueda en base a
un nombre de persona o a un número de teléfono, según como implementes la
función de devolución de llamada (la función BuscarPersona en el ejemplo que
te he indicado anteriormente), devolviéndote el objeto CPersona encontrado,
pero al segundo tendrás que pasarle un valor de clave (en tu caso será el
número de teléfono, que es la clave por la que se encuentran ordenados los
objetos CPersona dentro de la colección aDatosOrdenados) y un objeto
CPersona, para saber si el número de teléfono especificado se corresponde
con el número de teléfono del objeto CPersona pasado al método
«TryGetValue», devolviéndote un valor Boolean. No sé si me he explicado
bien:

Find --> Te dice si un número de teléfono está dentro de la colección
devolviéndote el objeto CPersona que lo contiene.

TryGetValue  --> Te dice si el número de teléfono que has indicado
se corresponde con el objeto CPersona especificado.

¿Observas la diferencia? :-)

--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.

buscar en colecciones genericas

grupo_noticia posted on Saturday, June 07, 2008 8:07 AM

Todos los objetos consumen en mayor o en menor medida recursos, y las
colecciones no son menos, aunque algunas consuman más recursos que otras.
Como ya he comentado, tengo entendido que la que más consume es el objeto
«SortedList», que entre otras implementa las interfaz «IDictionary». Ahora,
aquellas que implementan «IList», parece ser que consumen menos, aunque
tampoco te lo puedo afirmar, porque tampoco tengo demasiada información al
respecto.

De todas maneras, las intefaces solamente se limitan a definir las
propiedades y métodos que forman la interfaz propiamente dicha, siendo las
clases que implementan dicha interfaz, las que se encargan de ejecutar el
código fuente apropiado en cada caso, por tanto, son éstas las causantes que
se consuman más o menos recursos.

--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.

HolaCuando dices q SortedList consume mas recursos te refieres a memoia o

SergioT posted on Saturday, June 07, 2008 11:24 AM

Hola

Cuando dices q SortedList consume mas recursos te refieres a memoia o tiempo
de procesamiento en la busqueda? por que si es memoria, la verdad no me
preocupa mucho, me preocupa más  el tiempo de procesamiento.. Pero entiendo
que si maneja pares de clave y valor debe internamente tener un metodo de
busqueda no secuencial por tanto mas rapido no?

No llego a entender lo que implicas con :

Por lo que vi TryGetValue recibe 2 parametros el primero la clave de
busqueda y el segundo un  objeto por referencia del tipo almacenado, en el
cual devuelve la referencia a la instancia que halla en la coleccion dada la
clave o nothing en caso que no halle, por tanto me parece que se comportaria
igual que el find, por lo menos esa impresión me da en el uso que le estoy
dando. Si me aclaras tu punto te agradeceria, siempre en bueno aprender

Me voy a dar un tiempito este fin de semana para probar el desempeño de
ambos métodos con colecciones de unos 1000 elementos haber que resulta, creo
que será interesante probar el tema no crees?

Salu2
Sergio

noticias:30F916C6-C486-44DD-8843-11EF79F5ED54@microsoft.com...

buscar en colecciones genericas

grupo_noticia posted on Saturday, June 07, 2008 12:05 PM

Me refiero a que el rendimiento general de la aplicación se verá afectado.
Si son pocos objetos, y dispones de bastante memoria RAM, pues lo mismo ni
se nota, pero si te vas a dedicar a almacenar en la colección una cantidad
importante de objetos, lo mismo puedes observar que la aplicación se ejecuta
con una cierta lentitud.

Tienes que tener en cuenta que la clase SortedList almacena una colección de
pares clave/valor ORDENADOS por la clave que le hayas indicado, y cada vez
que añadas un nuevo elemento, éste se ordenará internamente, y ésto, pues
necesariamente lleva su tiempo: a más elementos, digo yo que se tardará más
tiempo en ordenarlos.

En fin, haz tu mismo las pruebas y compara resultados.



Olvídate de lo que te indiqué anteriormente, y la verdad que ahora mismo
ignoro el motivo por el cual lo dije. Quizás estube realizando otras pruebas
que no confirman las que acabo de realizar.

Efectivamente, si le pasas al método «TryGetValue» un número de teléfono
cualquiera, te devolverá el objeto CPersona pasado por refencia, si es que
existe algún objeto CPersona incluido en la colección con el número de
teléfono especificado; igual que el método «Find».


--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.

a la espera de algun experto, pej.

Ivan posted on Sunday, June 08, 2008 5:24 AM

a la espera de algun experto, pej. prueba a implementar los metodos
Contains y/o IndexOf en tu coleccion (si es que como me ha dado la
impresion has creado una coleccion personalizada basada
collectionBase).

Supongo que podria ser algo asi=3D>

Function indexOf(ByVal value As Object) As Integer
Return List.IndexOf(value)
End Function
Function Contains(ByVal value As Object) As Boolean
Return List.Contains(value)
End Function

aunque si por lo que dices quieres almacenar el telefono asociado a la
'persona', quizas te interesase mas derivar de la clase DictionaryBase
e implementar (aparte del metodo Add, claro) las propiedades Item,
Contains, y quizas alguna otra. El sistema seria similar al de List
pero almacenarias pares de clave y valor

bueno, no me hagas demasiado caso, pues realmente ahora estoy
empezando a estudiarlo y no estoy muy seguro, pero creo que los tiros
podrian andar por ahi

un saludo
Ivan

disculpas pero en la funcion CopiaNivel =3D>aqui =3D>en realidad habria que

Ivan posted on Sunday, June 08, 2008 5:24 AM

disculpas pero en la funcion CopiaNivel =3D>

aqui =3D>


en realidad habria que usar el condtructor de la clase nivel que no lo
a=F1ade a la coleccion =3D>

Dim fNivel As New Nivel(clave)

pues sino, aparte de obtener seguramente un error, como poco
sustituiriamos el elemento por uno nuevo aunque con el mismo Id.

en  mi caso simplemente no cearia el nivel y el error lo daria despues
por objero inexistente (por el codigo del new)

sorry, se me habia colado

un saludo
ivan

buscar en colecciones genericas

Ivan posted on Sunday, June 08, 2008 5:24 AM

gracias de nuevo y un saludo
Ivan



.
o
=BB. Ahora,
e
al
as
es que
l
n
o o

Hola Enrriquete cuentoq eu hice pruebas de las colecciones List(Of T) y

SergioT posted on Thursday, June 19, 2008 10:40 AM

Hola Enrrique

te cuentoq eu hice pruebas de las colecciones List(Of T) y SortedList(of
TKey, TValue) y el resultado me dejó impresionado
hice la comparacion con 4 tipos de busquedas asi:

1 la carga de 1000000 de objetos en la coleccion
2 buscando el ultimo elemento de la coleccion cargada

los 4 casos son
Un sortedlist
Un List(of T)
implementando el Find
usando un For secuencial para recorrer la coleccion
usando un For each secuencial para recorrer la coleccion

Resultados:
El mejor método de busqueda es sin lugar a duda el sortedList ya que no
tarda ni 1 milisegundo, impresionante, pero la carga del 1000000 de objetos
es demasiado lenta 12 minutos en mi maquina!!,esto hace que no tenga sentido
usar  el sortedlist a no ser para colecciones chicas

La carga del 1000000 de objetos con el List es miles de veeces mas rapido,
solo 3 segundos y la busqueda usando el metodo find es de aprox un segundo
pero la busqueda con el viejo for o for each es de solo 80 milisegundos!!!

Bien asunto sellado, lo mejor es el viejo metodo secuencial jeje que
cosas!!!


Salu2
SergioT



noticias:48A28A0E-1396-49BB-9F3B-67470C0D9BD8@microsoft.com...


Didn't Find The Answer You Were Looking For?

EggHeadCafe has experts online right now that may know the answer to your question.  We pay them a bonus for answering as many questions as they can.  So, why not help them and yourself by becoming a member (free) and ask them your question right now?
Create Account & Ask Question In Live Forum





Pete's Resume  |  Robbe's Resume  |  Neado  |  Free Icons  |  Privacy  |   (c) 2010