Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 20-06-2007
Avatar de david_uh
david_uh david_uh is offline
Miembro
 
Registrado: may 2007
Ubicación: Arequipa, Perú
Posts: 227
Poder: 18
david_uh Va por buen camino
Búsqueda en listbox

hola a todos
tengo el siguiente problema:
tengo un listbox cargado con 10000 nombres de clientes y por cada entrada en la lista le he relacionado un ID de tipo integer este valor lo he almacenado de esta forma
Código:
while not ZListas.Eof do                //
        begin
            lis_clientes.Items.Add(ZListas.FieldByName('cliente').AsString + ^I +
                                   ZListas.FieldByName('Direccion').AsString);
            lis_clientes.Items.Objects[i] := pointer(ZListas.FieldByName('Id').AsInteger);
            inc(i);
            ZListas.Next;
        end;
pero ahora necesito recuperar enun Edit el nombre de un cliente y para ello cuento solo con su ID, es obvio que tendria que buscar el id dentro de la matriz objects[] de la lista pero me gustaria saber si existe otra forma ya que una búsquda sobre 10000 registros o más podría no ser eficiente

Gracias de antemano por cualquier alcance
Responder Con Cita
  #2  
Antiguo 20-06-2007
Avatar de cHackAll
[cHackAll] cHackAll is offline
Baneado?
 
Registrado: oct 2006
Posts: 2.159
Poder: 20
cHackAll Va por buen camino
Cool Ok

Cita:
Empezado por david_uh
...una búsquda sobre 10000 registros o más podría no ser eficiente...
bueno no estoy muy de acuerdo con esa forma de pensar pues de todas formas los programas deben realizar dicha busqueda internamente para encontrar los datos que el usuario requiere... imaginate al hacer una consulta SQL lo que debe hacer para hacer un simple
Código SQL [-]
select * from Empleados where Cargo like 'Gerente*'
... en defintiva hay metodos de optimizacion que utilizaron los creadores del motor pero en todo caso en algun momento debe hacer un "barrido" de cada uno de los registros de tal tabla.

Pero bueno, si lo que buscas es acortar la cantidad de lineas utilizadas en tu código fuente os dejo la siguiente:

Código Delphi [-]
 Posicion := lis_clientes.Items.IndexOfObject(Pointer(12));

Buscamos el puntero $12 y su posicion la guardamos en una variable, siendo un -1 = "not found".

Saludos
Responder Con Cita
  #3  
Antiguo 20-06-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.293
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
En este caso y para modificar el mínimo código posible, yo optaría por una segunda lista (TStringList) "ordenada" por ID que te permita hacer la búsqueda. En la segunda lista guardaría el ID y en el Objects puedes guardar el indice de la primera lista donde se encuentra ese elemento.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #4  
Antiguo 20-06-2007
Delfino Delfino is offline
Miembro
 
Registrado: jul 2003
Ubicación: Madrid
Posts: 974
Poder: 21
Delfino Va por buen camino
Si son solo dos datos ID + Nombre, mas eficiente seria almacenar en la lista valores en formato Name=Value, asi seria ID=Nombre,
para obtener el ID utilizar la propiedad Names[i] de la StringList y para obtener el nombre la propiedad Values[ID]..
__________________
¿Microsoft? No, gracias..
Responder Con Cita
  #5  
Antiguo 20-06-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.293
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por Delfino
Si son solo dos datos ID + Nombre, mas eficiente seria almacenar en la lista valores en formato Name=Value, asi seria ID=Nombre,
para obtener el ID utilizar la propiedad Names[i] de la StringList y para obtener el nombre la propiedad Values[ID]..
Es una forma correcta, pero el problema es que ya no funciona la búsqueda dicotómica. El acceso utilizando Value[ID] es secuencial (que es lo que no quiere hacer).
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #6  
Antiguo 20-06-2007
Avatar de david_uh
david_uh david_uh is offline
Miembro
 
Registrado: may 2007
Ubicación: Arequipa, Perú
Posts: 227
Poder: 18
david_uh Va por buen camino
Cita:
Empezado por cHackAll
Código SQL [-]select * from Empleados where Cargo like 'Gerente*'

... en defintiva hay metodos de optimizacion que utilizaron los creadores del motor pero en todo caso en algun momento debe hacer un "barrido" de cada uno de los registros de tal tabla.

Pero bueno, si lo que buscas es acortar la cantidad de lineas utilizadas en tu código fuente os dejo la siguiente:


Código Delphi [-]
Posicion := lis_clientes.Items.IndexOfObject(Pointer(12));





Buscamos el puntero $12 y su posicion la guardamos en una variable, siendo un -1 = "not found".

Saludos
bueno el hecho es que para optimizar la velocidad de ingreso de datos he hecho lo siguiente:
primero una consulta
Código SQL [-]
 
Select id,cliente from tblClientes order by Cliente
así ordenado por cliente este va a para a la lista, el usuario en un edit escribe y el la lista se van seleccionando las coincidencias parecida a la ayuda de windows 95 y para ello necesito la lista ordenada, no la ordeno son el metodo Sort de la lista ya que tarda demasiado, pero el caso es que las ID no estan ordenadas y una búsqueda binaria no es viable, ahora mi pregunta es el método:
Código Delphi [-]
 
 Posicion := lis_clientes.Items.IndexOfObject(Pointer(12));
no entiendo bien el Pointer(12) a que se refiere? que es el 12? el ID del cliente???, la búsqueda así es secuencial?
gracias por cualquier respuesta
Responder Con Cita
  #7  
Antiguo 20-06-2007
Avatar de cHackAll
[cHackAll] cHackAll is offline
Baneado?
 
Registrado: oct 2006
Posts: 2.159
Poder: 20
cHackAll Va por buen camino
Cool Sip

Cita:
Empezado por david_uh
...pero ahora necesito recuperar enun Edit el nombre de un cliente y para ello cuento solo con su ID, es obvio que tendria que buscar el id dentro de la matriz objects[] de la lista pero me gustaria saber si existe otra forma ya que una búsquda sobre 10000 registros o más podría no ser eficiente...
Lamento no haber sido del todo claro al responder la interrogante... solo contando con el ID en mi ejemplo el ID es 12, pero supongo que el ID lo obtienes de una variable o objeto en la GUI que lastimosamente desconozco... pero es la misma lógica utilizada;

Cita:
Empezado por Neftali
...yo optaría por una segunda lista (TStringList) "ordenada" por ID que te permita hacer la búsqued...
Esa idea esta super, lastimosamente debes llamar a un procedimiento de ordenamiento, un QuickSort pues la VCL no ordena por Objects , pero con eso ya estaríamos... la busqueda se vuelve más eficiente.

En todo caso respondo la pregunta:

Código Delphi [-]
 Posicion := lis_clientes.Items.IndexOfObject(Pointer(StrToInt(txtID.Text)));

Creo que la cosa ahora se entiende más.
Responder Con Cita
  #8  
Antiguo 20-06-2007
Avatar de david_uh
david_uh david_uh is offline
Miembro
 
Registrado: may 2007
Ubicación: Arequipa, Perú
Posts: 227
Poder: 18
david_uh Va por buen camino
ok gracias por el alcance.. a proposito el id se encuentra en el tag del edit donde el user escribe
Responder Con Cita
  #9  
Antiguo 20-06-2007
Avatar de cHackAll
[cHackAll] cHackAll is offline
Baneado?
 
Registrado: oct 2006
Posts: 2.159
Poder: 20
cHackAll Va por buen camino
Cool Me olvidaba

Cita:
Empezado por david_uh
...la búsqueda así es secuencial?...
Código Delphi [-]
function TStrings.IndexOfObject(AObject: TObject): Integer;
begin
  for Result := 0 to GetCount - 1 do
    if GetObject(Result) = AObject then Exit;
  Result := -1;
end;

Eso fue copiado de la misma VCL del Delphi, creo responde a la pregunta.

A lo otro un poco mas concreto:
Simplemente pones la linea que deje, y obtienes la posicion, con la posicion obtendras el nombre... por ejemplo

Código Delphi [-]
...
 Posicion := lis_clientes.Items.IndexOfObject(Pointer(txtID.Tag));
 if Posicion <> -1 then
  txtNombre.Text = lis_clientes.Items[Posicion];
...

Creo que ahorras algo de código, suerte!
Responder Con Cita
  #10  
Antiguo 20-06-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Y bueno, ¿qué no sería mejor usar un dbgrid con índices bien puestos en la tabla y consultas sql apropiadas?

// Saludos
Responder Con Cita
  #11  
Antiguo 20-06-2007
Avatar de david_uh
david_uh david_uh is offline
Miembro
 
Registrado: may 2007
Ubicación: Arequipa, Perú
Posts: 227
Poder: 18
david_uh Va por buen camino
Cita:
Empezado por roman
Y bueno, ¿qué no sería mejor usar un dbgrid con índices bien puestos en la tabla y consultas sql apropiadas?

// Saludos
pense en hacer eso, es decir usando la propiedad filter. además como el ingreso de datos es intenso a medida que crece la tabla es más lento aún, poor ello utilizo la busqueda en la lista
Responder Con Cita
  #12  
Antiguo 20-06-2007
Avatar de cHackAll
[cHackAll] cHackAll is offline
Baneado?
 
Registrado: oct 2006
Posts: 2.159
Poder: 20
cHackAll Va por buen camino
Cool Ok

Cita:
Empezado por roman
...no sería mejor usar un dbgrid con índices bien puestos en la tabla y consultas sql apropiadas?...
Dijo alguien una vez "eso es harina de otro costal"... pues yo, si es que considero que la mejor forma de hacer algo sea por una mejor apariencia en la GUI u otra causa pues lo hago de una forma poco común. Creo que saber qué es lo mejor en este puno, está en funcion al por qué lo hizo el iniciador del hilo de esa forma.

Saludos!
Responder Con Cita
  #13  
Antiguo 20-06-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por david_uh
pense en hacer eso, es decir usando la propiedad filter. además como el ingreso de datos es intenso a medida que crece la tabla es más lento aún, poor ello utilizo la busqueda en la lista
Claro que va a ser lento. Pero eso es porque no estás uando adecuadamente las herramientas. No lo tomes a mal, es sólo que un ListBox no es el componente adecuado para atacar bases de datos, y si lo usas, al menos deberías hacerlo en modo virtual. Usar filtros tampoco es adecuado. El punto aquí es: no necesitas tener 10,000 registros al mismo tiempo en tu aplicación. Haz una ventana de inserción/modificación de datos que trabaje con un registro a la vez. Y haz una ventana de búsqueda que permita al usuario escoger criterios de filtrado. Esto no lo traduces en la propiedad Filter del dataset, sino en una cláusula WHERE de una consulta SQL. La consulta, ya con los criterios, la ejecutas para traer a tu aplicacíon, sólo los registros necesarios.

// Saludos
Responder Con Cita
  #14  
Antiguo 20-06-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por cHackAll
Dijo alguien una vez "eso es harina de otro costal"... pues yo, si es que considero que la mejor forma de hacer algo sea por una mejor apariencia en la GUI u otra causa pues lo hago de una forma poco común. Creo que saber qué es lo mejor en este puno, está en funcion al por qué lo hizo el iniciador del hilo de esa forma.

Saludos!
Amigo cHackAll, estoy de acuerdo en que es harina de otro costal. Estrictamente hablando, se preguntó acerca de un listbox, y usar un dbgrid es otro cantar. Pero considero que a veces podemos ayudar más orientando acerca de otras opciones que quien pregunta quizá no conozca. Claro que puedo equivocarme, pero en este caso, me da la impresión de que nuestro amigo no tiene clara la manera de trabajar este tipo de cosas y por ello intenta usar un recurso inadecuado.

// Saludos
Responder Con Cita
  #15  
Antiguo 21-06-2007
Avatar de david_uh
david_uh david_uh is offline
Miembro
 
Registrado: may 2007
Ubicación: Arequipa, Perú
Posts: 227
Poder: 18
david_uh Va por buen camino
bien solo necesitaba que la lista vaya mostrando las coincidencias mientras el usuario escribe, un dbgrid no seria eficiente para ello me parece al tratarse de muchos registros
gracias por todo
Responder Con Cita
  #16  
Antiguo 21-06-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.293
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por cHackAll
Esa idea esta super, lastimosamente debes llamar a un procedimiento de ordenamiento, un QuickSort pues la VCL no ordena por Objects , pero con eso ya estaríamos... la busqueda se vuelve más eficiente.
Creo que no me expliqué bien. Se trata de usar el ID para ordenar en la segunda lista (ID como String) y usar así búsqueda dicotómica/binaria sobre la segunda lista (auxiliar) y cada ID de la segunda lista apunta a la posición correspondiente de la primera "Buscar_ datos_ con_ listas_ ordenadas.zip"

He usado 25000 líneas para maximizar los resultados y he realizado las búsquedas utilizando las dos formas; La inicial (secuencial) y usando dos listas para obtener búsqueda dicotómica.

Sorpredentemente al buscar un único elemento, casi no se aprecia, lo que significa que la secuencial se hace más rápido de lo que yo pensaba; Ahora, si el proceso se maximiza (por ejemplo haciendo 1000 búsquedas seguidas) la diferencia es apreciable (más que apreciable).

Revisad el código si queréis, veréis que la diferencia para usar la lista auxiliar son unas pocas líneas.

La diferencia está en usar:

Código Delphi [-]
    if (j > 0) then begin
      ListBox1.Items.Add(ADOTable1.FieldByName('Nombre').AsString + ' - '  +
                         ADOTable1.FieldByName('Direccion').AsString + ' - ' +
                         IntToStr(j));
      ListBox1.Items.Objects[i] := pointer(j);
    end;

o esto:

Código Delphi [-]
if (j > 0) then begin
      Index := ListBox1.Items.Add(ADOTable1.FieldByName('Nombre').AsString + ' - '  +
                         ADOTable1.FieldByName('Direccion').AsString + ' - ' +
                         IntToStr(j));
      ListBox1.Items.Objects[i] := pointer(j);

      // Añadimos a la segunda lista
      Index2 := _ListID.Add(IntToStr(j {ID}));
      _ListID.Objects[Index2] := Pointer(Index);
    end;

Link al ejemplo.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.

Última edición por Neftali [Germán.Estévez] fecha: 21-06-2007 a las 12:10:15. Razón: Corregido el link
Responder Con Cita
  #17  
Antiguo 21-06-2007
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Realmente impresionante los tiempos Neftali.

Dejo una pregunta: ¿no estaremos reinventando la rueda?

Aunque no he estudiado a fondo la implementación de un índice de Bases de datos, se supone que es muy parecido, entonces, ¿por qué implementar nosotros ese índice?(Básicamente es lo que hace Neftali) ya que tenemos la Base de Datos, que lo haga ella .

Si tenemos el ID, y ese campo es clave primaria de la tabla, hacer una consulta del tipo: "select NombreCliente from clientes where id = 32" debe ser inmediata. Si la consulta incluye parámetros y está preparada de antemano, más aún.

Si hablamos de bases de datos en red, peor aún, ya que otro usuario (o el mismo usuario desde otra ventana) puede insertar/borrar/modificar un cliente y tenemos que recargar esos datos del servidor, o tendremos que implementar un servicio de sincronización... o sea, que nos vamos metiendo en camisas de once varas. Quizás este punto no lo haya tenido en cuenta david_uh, no sé, ya nos contará.

Creo que lo dejo claro, tirar siempre de la base de datos y que me resuelva el problema.

Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.

Última edición por Lepe fecha: 21-06-2007 a las 16:10:57.
Responder Con Cita
  #18  
Antiguo 21-06-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.293
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por Lepe
¿no estaremos reinventando la rueda?
Bueno, yo me he basado en la premisa de un ListBox.

Supongo que si empezaramos de cero y los datos los tuvieramos en la Base de Datos, pues tal vez esa sería la mejor solución (y digo tal vez, porque no conocemos más detalles del problema en concreto).

También estaría la posibilidad de un TClientDataSet, dependiendo del tráfico de red generado y de las consultas que se fueran a relalizar.

Si se necesitan velocidad y muchas consultas de este tipo, esto puede ser una solición también óptima, ya que no necesita tráfico de red (sólo la carga inicial) y la velocidad en local es inigualable (por muchos íncides y preparadas que tengamos las consultas).

Lo de siempre, no creo que exista una mejor solución para todos los casos, depende, depende, depende,...
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #19  
Antiguo 21-06-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
De verdad que no entiendo porqué no usar un clientdataset u otro dataset en memoria y un dbgrid. Por otra parte, algo pasa con el ejemplo, que lo ejecuto y cargo los datos pero éstos nunca aparecen ni la busqueda presenta nada. ¿Hay algo que no sepa?

// Saludos
Responder Con Cita
  #20  
Antiguo 21-06-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.293
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por roman
...Por otra parte, algo pasa con el ejemplo, que lo ejecuto y cargo los datos pero éstos nunca aparecen ni la busqueda presenta nada. ¿Hay algo que no sepa?
Teóricamente con el EXE y el DATOS.TXT en el mismo directorio debería funcionar.
¿No será el tema del separador en el DATOS.TXT? Que no te lo está cogiendo bien; Recuerdo cuando hablamos del tema (hace no mucho en otro hilo), que si estaban configurados distintos había problemas. No todas formas no lo tengo claro, porque en la cadena de conexión ya va incluído el ;
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
.txt a listbox molinero1 Varios 3 26-04-2007 15:03:07
busqueda dentro de en un listbox Max_E. Varios 7 01-10-2006 07:51:52
listbox gsilvei Varios 2 06-09-2006 04:20:44
Uso de ListBox Luli Varios 3 14-04-2005 19:26:30
listbox cesarjbf OOP 1 16-10-2003 13:17:21


La franja horaria es GMT +2. Ahora son las 06:40:15.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi