Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

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

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 16-08-2012
sebamawa sebamawa is offline
Miembro
NULL
 
Registrado: ago 2012
Posts: 18
Poder: 0
sebamawa Va por buen camino
Ordenar e insertar ordenado en TObjectList

Hola a todos.

Me estoy iniciando en Delphi y me gustaría saber como ordenar una lista TObjectList según un campo clave de los objetos insertados en la lista. Leí por algún lado que se dispone del método Sort, pero no tengo claro su utilización.

Además me gustaría saber si hay algún método para insertar un objeto de forma ordenada en una lista TObjectList, también con respecto a un campo (propiedad) clave del objeto a insertar.

Muchas gracias.

Saludos.
Responder Con Cita
  #2  
Antiguo 16-08-2012
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
El método Sort de TObjectList recibe como parámetro una función (que tú defines) que le indica cómo debe comparar tus objetos. La función debe devolver un número positivo si el primer objeto es "mayor" que el primero, 0 si son iguales y un número negativo si el primer objeto es "menor" que el segundo.

Te pongo un ejemplo:

Código Delphi [-]
// Clase de los objetos que conforman la lista
TCliente = class
  Nombre: String;
  Telefono: String;
end;

// Función para comparar dos objetos (en este caso, compara los clientes por su nombre)
function ComparaClientes(Item1, Item2: Pointer): Integer;
begin
  if TCliente(Item1).Nombre > TCliente(Item2).Nombre then
    Result := 1 // > 0
  else if TCliente(Item1).Nombre = TCliente(Item2).Nombre then
    Result := 0
  else
    Result := -1 // < 0;
end;

// Ejemplo de uso:
Lista.Sort(ComparaClientes);

Me parece que TObjectList no tiene forma de insertar ordenadamente.

// Saludos
Responder Con Cita
  #3  
Antiguo 16-08-2012
sebamawa sebamawa is offline
Miembro
NULL
 
Registrado: ago 2012
Posts: 18
Poder: 0
sebamawa Va por buen camino
Gracias roman por tu respuesta.
Al hacer el llamado con (según tu ejemplo):
Cita:
Lista.Sort(ComparaClientes);
el IDE me dice que no le estoy pasando la cantidad correcta de parámetros a la función ComparaClientes.
¿Cuál es el problema?. Yo vengo de Pascal estándar, y estoy aprendiendo no hace tanto programación a objetos. Para mi habría que pasarle a la función dos punteros como parámetros, pero en este caso tal vez no sea así.

Otra pregunta, ¿ se dispone en Delphi de alguna lista "dinámica" predefinida para insertar objetos de forma ordenada ?.

Muchas gracias.

Saludos.

Última edición por sebamawa fecha: 16-08-2012 a las 19:03:56.
Responder Con Cita
  #4  
Antiguo 16-08-2012
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 sebamawa Ver Mensaje
Para mi habría que pasarle a la función dos punteros como parámetros
No, porque entonces estarías pasando al método Sort el resultado de comparar dos objetos en específico. El parámetro de Sort es una función (no el resultado de una función). Pasar funciones o procedimientos como parámetros se usa desde el pascal estándar.

Necesitaría ver el código exacto que estás usando para ver porqué el compilador te marca ese error.

// Saludos
Responder Con Cita
  #5  
Antiguo 16-08-2012
sebamawa sebamawa is offline
Miembro
NULL
 
Registrado: ago 2012
Posts: 18
Poder: 0
sebamawa Va por buen camino
Entiendo roman, es clara tu explicación y mala mi interpretación previa.
Haber si con parte del código se logra detectar el error.

En una unidad (UPersona) declaro un objeto persona de la siguiente forma:

Código:
TPersona = class
   private
     documento: Integer;
     nombre: String;
   public
     (* Constructores *)
     Constructor Create(doc: Integer; nom: String);
     
      (* Selectoras *)
      Function GetDocumento: Integer;
      Function GetNombre: String;

      (* Modificadoras *)
      Procedure SetDocumento(doc: Integer);
      Procedure SetNombre(nom: String);
   end;

implementation
  ...
end.
Luego en un TForm aparecen estos procedimientos asociados a dos botones.
Primero declaro las variables
Código:
var
  Form1: TForm1;
  p: TPersona;
  listaPersonas: TObjectList;
Primer botón:

Código:
procedure TForm1.Button1Click(Sender: TObject);
begin
  p:=TPersona.Create(StrToInt(Edit1.Text),Edit2.Text);
  listaPersonas:=TObjectList.Create(True);

  // Agregamos el objeto persona a la lista
  listaPersonas.Add(p);

  Edit1.Text:='';
  Edit2.Text:='';
end;
La idea es que cada vez que se presiona el botón Button1 se agrege un objeto persona a la lista TObectList, cuyos campos (documento y nombre) se leen desde dos TEdits.

Ahora el segundo botón:
Código:
procedure TForm1.Button2Click(Sender: TObject);
 function OrdenarPorDocumento(a: Pointer;b: Pointer): Integer;
 begin
   if TPersona(a).GetDocumento > TPersona(b).GetDocumento then
     result:=-1
   else
     if TPersona(a).GetDocumento < TPersona(b).GetDocumento then
       result:=1
     else
       result:=0;
 end;

begin
  ListaPersonas.Sort(OrdenarPorDocumento);
end;
La idea es que cuando se apreta el segundo botón (Button2) se ordene la lista.

Desde ya muy agredecido por cualquier comentario.

Saludos.
Responder Con Cita
  #6  
Antiguo 16-08-2012
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
Así, a bote pronto, lo único que se me ocurre es que declares la función OrdenarPorDocumento fuera del evento Button2Click. Es posible que los procedimientos locales no se puedan pasar como parámetros. Nunca lo he intentado.

// Saludos
Responder Con Cita
  #7  
Antiguo 16-08-2012
sebamawa sebamawa is offline
Miembro
NULL
 
Registrado: ago 2012
Posts: 18
Poder: 0
sebamawa Va por buen camino
Gracias roman por tu orientación.
Veré si puedo solucionar el problema.
Saludos.
Responder Con Cita
  #8  
Antiguo 17-08-2012
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

Hice unas pruebas y si la función pasada como argumento está fuera del procedimiento/función (que es como la he usado anteriormente) se la puede llamar:
Código Delphi [-]
  Lista.Sort(Compare);

Ahora, enviando como argumento la dirección de la función como menciona sebamawa, y figura en el ejemplo de la ayuda de Delphi:
Código Delphi [-]
  Lista.Sort(@Compare);
la llamada trabaja tanto si la función es anidada como si es externa.


También es muy interesante tu enfoque Neftali

Saludos.
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #9  
Antiguo 28-08-2012
sebamawa sebamawa is offline
Miembro
NULL
 
Registrado: ago 2012
Posts: 18
Poder: 0
sebamawa Va por buen camino
Buscar y eliminar un objeto de un TObjectList

Hola a todos nuevamente !!!
Para eliminar un objeto de una lista TObjectList tenemos el método Remove; ahora para buscar un objeto en la misma por un campo clave hay algún método predefinido?. En caso de no haberlo, sería viable implementar un procedimiento que realice una búsqueda binaria, como propuso Roman para la inserción de objetos en una lista ?
Me podrían poner un ejemplo de este caso, por ejemplo si se tiene una lista de objetos (persona) y se quiere eliminar una persona según un número de documento que se ingrese para la búsqueda. Tengan presente que la lista está ordenada de forma ascendente según los números de documentos.
Desde ya muchas gracias.
Saludos.
Responder Con Cita
  #10  
Antiguo 28-08-2012
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola sebamawa.

Si la lista ya está ordenada podes usar una búsqueda binaria. Tomemos como ejemplo una reducción de la clase que puso de ejemplo roman:
Código Delphi [-]
implementation

type
  TCliente = class
    Nombre: String;
  end;

var
  LstObj : TObjectList;
  Cliente : TCliente;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  LstObj := TObjectList.Create;
  // Demás operaciones de carga
  ...
end;

function TForm1.BinarySearch(OLst: TObjectList; Valor: string): Integer;
var
  Pri, Ult, Med : Integer;
  Esta : boolean;
begin
   Pri  := 0;
   Ult  := OLst.Count-1;
   Esta := False;
   while (Pri <= Ult) and not Esta do
   begin
      Med := (Pri + Ult) div 2;
      if TCliente(OLst.Items[Med]).Nombre = Valor then Esta := true;
      if TCliente(OLst.Items[Med]).Nombre < Valor then Pri  := Med + 1;
      if TCliente(OLst.Items[Med]).Nombre > Valor then Ult  := Med - 1;
   end;
   if Esta then
     Result := Med
   else
     Result := -1;
end;

// Ejemplo de llamada:
procedure TForm1.Button1Click(Sender: TObject);
var
  P : Integer;
begin
  P := BinarySearch(LstObj, 'Juan Perez');
  if P <> -1 then
    ShowMessage('Nombre:   ' + TCliente(LstObj.Items[P]).Nombre+#10#13+
                'Posición: ' + IntToStr(P));
  //  ...
end;

...

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(LstObj) then
    LstObj.Free;
end;

Saludos.
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #11  
Antiguo 28-08-2012
sebamawa sebamawa is offline
Miembro
NULL
 
Registrado: ago 2012
Posts: 18
Poder: 0
sebamawa Va por buen camino
Muchas gracias ecfisa, algo como lo que planteaste tenía en mente y resulta de mucha ayuda.
Como he comentado, vengo de Pascal Estándar, o sea de arreglos estáticos, crear listas enlazadas desde cero, etc, y estoy tratando de migrar algunas estructuras de datos a Delphi como listas enlazadas y arboles, pero claro, Delphi ya tiene incorporadas muchas de estas estructuras o algunas semejantes que facilitan el tener que empezar a programar desde cero, supongo que esto se da en todo lenguaje moderno.
Me podrías decir donde encontrar descripciones de los métodos y propiedades de las clases de Delphi, es que a veces cuando tengo que realizar una tarea caigo en la duda si, es que tengo una rutina predefinida o no, y en este último caso debo implementar la misma por mi cuenta.
Otra duda, el método FindInstanceOf de la clase TObjectList, qué tarea realiza?
Y lo último, teniendo la posibilidad de realizar búsquedas binarias en una lista (TObjectList por ejemplo), sabiendo que este tipo de búsqueda es muy eficiente, tiene sentido el utilizar árboles para el guardado de datos?
Tal vez más de uno me dirá que use base de datos, pero antes quiero manejar con solvencia las estructuras de datos que menciono antes.

Muchas gracias.
Saludos para todos.
Responder Con Cita
  #12  
Antiguo 28-08-2012
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola sebamawa.

Cita:
Me podrías decir donde encontrar descripciones de los métodos y propiedades de las clases de Delphi
En la propia ayuda de Delphi encontras descrita las clases, sus propiedades y métodos. Sobre TList,TQueue,TStrings, etc revisa este enlace.

Cita:
Otra duda, el método FindInstanceOf de la clase TObjectList, qué tarea realiza?
Busca la primera ocurrencia de una clase específica dentro de la lista. Si la clase buscada no existe devuelve el valor -1.

Saludos.
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #13  
Antiguo 28-08-2012
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Cita:
Empezado por sebamawa Ver Mensaje
tiene sentido el utilizar árboles para el guardado de datos?
Tal vez más de uno me dirá que use base de datos, pero antes quiero manejar con solvencia las estructuras de datos que menciono antes.

Muchas gracias.
Saludos para todos.
¿Árboles? Pasar de un TAD lista a un TAD árbol no es poca cosa. En primer lugar habría que determinar si efectivamente tiene sentido alguno (sobre todo en lo lógico) el almacenar datos en forma de árbol.
Desconozco si Delphi provee de fábrica un TObjectTreeList (por darle un nombre) pero me parece que el que consideres pensar en árboles, y que luego sobre este posiblemente se deba implementar y adaptar los algoritmos de insersión, ordenamiento y búsquda es ya algo exagerado y una pérdida de tiempo.

Lo mejor es que le dejes eso al motor de base de datos... que lo hace estupéndamente. Si ya de hecho los motores por dentro poseen árboles para estructurar los datos. Concretamente los B+ tree.

Luego es que existen tus clase del dominio, y crearás tantos objetos como registros tengas. Al extraer los registros pasas los datos a cada instancia en sus correspondientes campos. Y el paso inverso, desde tu clase del dominio lees sus campos y mandas a ejecutar una instrucción INSERT o UPDATE sea el caso.
A estas alturas y si quieres seguir avanzando de escala ya te vas pensando en un framework de persistencia.

Me parece que te estás complicando las cosas innecesariamente.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #14  
Antiguo 28-08-2012
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 ecfisa Ver Mensaje
Si la lista ya está ordenada podes usar una búsqueda binaria.
De hecho, modificando un poco, la misma función que se usa para la inserción se puede usar para la búsqueda. Es decir, se hace una sóla función de búsqueda que devuelva el índice donde debe ir el objeto. Ese índice se usa, bien sea para insertar un nuevo objeto, o bien para devolver la posición del objeto buscado.

// Saludos
Responder Con Cita
  #15  
Antiguo 29-08-2012
sebamawa sebamawa is offline
Miembro
NULL
 
Registrado: ago 2012
Posts: 18
Poder: 0
sebamawa Va por buen camino
Estimados amigos, primero que nada les agradezco sus sugerencias y ayuda.
Estoy de acuerdo con lo que dice Delphius, estoy complicando las cosas, y seguramente eso se de porque aún me falta aprender muchas herramientas de Delphi.
Lo he dicho más de una vez, mi base previa en programación es Pascal Estándar, un curso con FreePascal y otro con Modula2 (que básicamente es Pascal para trabajar de forma modular).
Con los compiladores anteriores sólo trabajabamos con la consola Dos, o sea, todas las salidas se realizaban de modo texto en la consolita. Los cursos que mencioné estaban enfocados a adquirir los rudimentos de la programación estructurada (con FreePascal) y la programación modular (Modula2).
Prácticamente todo lo hacíamos desde cero, listas enlazadas, árboles, arreglos con tope, etc; claro que no eran superaplicaciones ni mucho menos lo que realizabamos partiendo "desde la nada".
Pero de interfaces gráficas, nada de nada, es por ello que yo de forma autodidacta he querido sumergirme un poco en la programación con interfaces de este tipo, y para ello elegí Delphi, pues es una forma de seguir conectado con Pascal.
Pero, está recontra claro, que la potencialidad y las herramientas de Delphi te ahorran mucho trabajo, y es por ello que a veces sin quererlo complico un poco las cosas queriendo traer algunas estructuras de Pascal Estándar que ya están predefinidas en Delphi como TAD's.

Nuevamente gracias, y espero se entienda en parte por qué he planteado ciertas dudas.
Saludos.
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
adotable ordenado por un campo leorene Conexión con bases de datos 2 13-02-2007 01:00:16
Select ordenado por un campo pero localizado por otro ingel SQL 2 04-01-2006 17:33:23
Imprimir el listado ordenado por un campo ilichhernandez Impresión 3 03-11-2005 19:44:13
DBLookupComboBox ordenado Supermagayin Conexión con bases de datos 2 12-04-2005 00:18:33
Grid ordenado al añadir registro Tomás Varios 0 13-03-2004 14:58:02


La franja horaria es GMT +2. Ahora son las 09:52:16.


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