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 02-02-2005
Feñiz Feñiz is offline
Miembro
 
Registrado: may 2003
Posts: 20
Poder: 0
Feñiz Va por buen camino
Ordenar un array de records

Tengo un array de records, donde luego cada record tiene una serie de campos. Necesito ordenar el array según uno de los campos, y mi pregunta es si existe alguna función en Delphi que lo haga automáticamente. Si no es así, ya sé que tendré que implementar un algoritmo de ordenación (la burbuja, quick sort, etc), pero si ya hay función que lo haga, pues me lo ahorro.

Por si no me he explicado bien, mi array sería del tipo:
Código Delphi [-]
type
  Registro= record
    Nombre, Direccion: String;
    Fecha: TDateTime;
  end;

var Lista: Array of Registro
Y necesitaría luego ordenar el array "Lista" según el campo "Fecha". La cosa es bastante más compleja, pero lo he simplificado mucho para que sea más fácil de entender lo que pregunto
Responder Con Cita
  #2  
Antiguo 02-02-2005
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
No recuerdo que haya nada para este efecto. Sin embargo podrías considerar usar un TList en lugar de un arreglo ya que esta clase sí tiene incorporado un método de ordenación al cual únicamente tienes que pasarle una función de comparación que dictamine cuando un elemento es menor que otro. El algoritmo que usa es el QuickSort.

// Saludos
Responder Con Cita
  #3  
Antiguo 02-02-2005
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 28
Lepe Va por buen camino
Pues yo propongo un TobjectList de esta forma quedaría algo así:
Código Delphi [-]
type Tregistro = record
       ...
       end

type TObjeto = class(Tobject)
   public 
      Datos:TRegistro
   end;
var  TLista :TobjectList;
Básicamente es lo mismo que propone Roman, pero te ahorras el uso de punteros, siempre trabajas con objetos. Ganas claridad conceptual y de código.

Saludos
Responder Con Cita
  #4  
Antiguo 03-02-2005
Feñiz Feñiz is offline
Miembro
 
Registrado: may 2003
Posts: 20
Poder: 0
Feñiz Va por buen camino
Gracias por la idea a los dos

Lepe, intento hacer lo que me has comentado, pero no entiendo muy bien cómo va la definición de Objetos y variables que haces. Si fueras tan amable de explicar un poco en qué consiste.... y cómo se trabaja luego con el TobjectList, que el tema se me escapa un poco.
Responder Con Cita
  #5  
Antiguo 03-02-2005
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 28
Lepe Va por buen camino
A ver si queda más claro.
Código Delphi [-]
type Tregistro = record
  Registro= record
   Nombre, Direccion: String;
    Fecha: TDateTime;
    end

type TCliente = class(Tobject)
   public 
      Datos:TRegistro
   end;

var  TLista :TobjectList;

implementation



procedure Tform1.Button1Click(sender:Tobject);
var c:TCliente;
   i:integer;
begin
  Lista := TobjectList.Create(true); //Creo la lista y la mantengo en memoria siempre
for i:=1 to 6 do //creo 6 clientes 
begin
  c := Tcliente.Create; // creo el cliente
  c.Datos.Nombre := 'pepe '+inttostr(i);
  c.DAtos.Fecha := Now()- i ; // la fecha con algunos dias menos
  // rellenas los datos;
  lista.add(c); // añadimos el cliente a la lista;
end;

end;

procedure Tform1.Close(..);
begin
  Lista.Free; // libero la lista y todos los clientes que tenga dentro.
end;

Para recorrer la lista de objetos:
Código Delphi [-]
  for i:=0 to Lista.count-1 do
    with TCliente(lista.items[i]) do
      memo1.lines.add(datos.Nombre);
Si te fijas, cada vez que accedo a la propiedad Lista.items, tengo que hacer un casteo, es decir, la Lista no sabe que tipo de objeto tiene dentro, se lo dices mediante el cast .... Tcliente(lista.items[i])


Para ordenar la lista, tienes que hacer una funcion simple de comparación de 2 Objetos.
Código Delphi [-]
function OrdenaFecha(a: Pointer; b: Pointer): Integer;
begin
  if TCliente(a).Fecha > TNota(b).DAtos.Fecha then
    Result := 1
  else if TCliente(a).Fecha < TNota(b).DAtos.Fecha then
    Result := -1
  else
    Result := 0;
end;

Y para ordenar usarías la orden:
Código Delphi [-]
   Lista.Sort(@OrdenaFecha);
Esto es algo rarito, se le da la direccion de memoria donde está la funcion de ordenación; a partir de aquí, la lista ya sabe como comparar 2 objetos, y ordena la lista entera

Si quieres ordenar por Nombre, Create una funcion OrdenaPorNombre que haga la comparación, y devuelva -1, 1 o cero.

Si en algun momento quieres quitar un cliente, puedes hacerlo así:
Código Delphi [-]
   Tcliente(lista.items[2]).Free;// quito el tercero en la lista

Espero te ayude.

Saludos
Responder Con Cita
  #6  
Antiguo 03-02-2005
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
Todo esto está muy bien pero si ya va a usar objetos para mi que los registros salen sobrando. Es decir, en lugar de

Código Delphi [-]
type Tregistro = record
  Registro= record
   Nombre, Direccion: String;
    Fecha: TDateTime;
    end

type TCliente = class(Tobject)
   public 
      Datos:TRegistro
   end;

¿por qué no simplemente

Código Delphi [-]
type TCliente = class(Tobject)
   public 
     Nombre, Direccion: String;
     Fecha: TDateTime;
   end;

// Saludos
Responder Con Cita
  #7  
Antiguo 04-02-2005
Feñiz Feñiz is offline
Miembro
 
Registrado: may 2003
Posts: 20
Poder: 0
Feñiz Va por buen camino
Muchas gracias a los 2, lo he implementado utilizando el TObjectlist, y va perfectamente (por cierto, lo que comenta Roman también se me había pasado a mí por la cabeza al ver la respuesta de Lepe ).

Lo único que no entiendo muy bien es la función de ordenación que ha puesto Lepe:
Código Delphi [-]
function OrdenaFecha(a: Pointer; b: Pointer): Integer;
begin
  if TCliente(a).Fecha > TNota(b).DAtos.Fecha then
    Result := 1
  else if TCliente(a).Fecha < TNota(b).DAtos.Fecha then
    Result := -1
  else
    Result := 0;
end;
¿No debería ser así?:
Código Delphi [-]
function OrdenaFecha(a: Pointer; b: Pointer): Integer;
begin
  if TCliente(a).Fecha > TCliente(b).Fecha then
    Result := 1
  else if TCliente(a).Fecha < TCliente(b).Fecha then
    Result := -1
  else
    Result := 0;
end;

Teniendo en cuenta que la definición de TCliente es la que ha sugerido Roman, es decir:
Código Delphi [-]
type TCliente = class(Tobject)
   public 
     Nombre, Direccion: String;
     Fecha: TDateTime;
   end;
Responder Con Cita
  #8  
Antiguo 04-02-2005
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 28
Lepe Va por buen camino
jejeje, estan al quite

El final de mi mensaje incluía esa opción, pero lo quité por 2 razones:
- Si ya lo tienes todo implementado con Records, tienes menos modificaciones.
- Si ya guardas el archivo con un File of Trecord, puedes seguir usandolo con los objetos, sin tener que modificar nada.

Si haces la corrección que propone Roman, debes cambiar la función de ordenación como bien has sugerido, Feñiz.

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


La franja horaria es GMT +2. Ahora son las 01:58:18.


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