Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Ordenar un array de records (https://www.clubdelphi.com/foros/showthread.php?t=18114)

Feñiz 02-02-2005 03:04:20

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 ;)

roman 02-02-2005 03:25:48

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

Lepe 02-02-2005 10:58:40

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

Feñiz 03-02-2005 01:01:33

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.

Lepe 03-02-2005 20:48:22

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

roman 03-02-2005 23:14:12

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

Feñiz 04-02-2005 01:20:20

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;

Lepe 04-02-2005 08:19:28

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


La franja horaria es GMT +2. Ahora son las 08:41:48.

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