PDA

Ver la Versión Completa : ordenar un TList


elcigarra
18-09-2006, 20:35:19
Tengo una clase TObject (miclase) definida con variables de distintos tipos y una lista (TList) de objetos "miclase".
¿Es posible ordenar esa lista de a cuerdo a una solo de esas variables de miclase (de tipo string)?

dec
18-09-2006, 20:46:31
Hola,

Se me ocurre que derives una nueva clase de "TList" y añadas allí un método para realizar lo que precisas. No sé qué te parecerá... ;)

elcigarra
18-09-2006, 20:52:06
Podría, pero pensé que ya lo había. De hecho esperaba que me mencionaras el método "Sort" de la clase pero la verdad es que no entendí como usarlo y la ayuda de delphi no me aclaró mucho y no funciona en mi caso por alguna razón qu edesconozco. Tal vez no sirva para eso.

dec
18-09-2006, 21:01:35
Hola,

Pues sí, revisando la ayuda (que no se me ocurrió antes, la verdad) se ve que "TList" cuenta con un método "Sort" que puede ayudarte. Hay un ejemplo y todo...

The following code sorts the objects in a list in alphabetical order based on their names. It assumes that the list contains only component references.

The CompareNames function performs the comparisons between objects in the list. The list is sorted when the user clicks a button.


function CompareNames(Item1, Item2: Pointer): Integer;
begin
Result := CompareText((Item1 as TComponent).Name, (Item2 as TComponent).Name);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
List1.Sort(@CompareText);
end;

maeyanes
18-09-2006, 21:04:33
Para usar el método Sort de TList, necesitas crear una función que devuelva un Integer y reciba como parámetros dos punteros:


function Compare(Item1: Pointer; Item2: Pointer): Integer;
var
MiClase1: TMiClase;
MiClase2: TMiClase;

begin
MiClase1 := TMiClase(Item1);
MiClase2 := TMiClase(Item2);
if MiClase1.Propiedad > MiClase2.Propiedad then
Result := 1
else
if MiClase1.Propiedad = MiClase2.Propiedad then
Result := 0
else
Result := -1
end;



Saludos...

roman
18-09-2006, 21:09:29
Hay un ejemplo y todo...

Ejemplo que, me parece, no puede compilar. Mejor hacer como Marcos.

// Saludos

dec
18-09-2006, 21:24:27
Hola,

Y qué culpa tengo yo de que el ejemplo de la ayuda de Delphi tenga una pequeña errata, porque es lo que parece. Ahora, de la ayuda de Delphi este código que sí que compila, o sea, se puede hacer, perfectamente, como se dice en la ayuda. ;)


unit Unit1;

interface

uses
Forms, Classes, Controls, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
private
FMiLista: TList;
end;

var
Form1: TForm1;

type
TMiClase = class(TObject)
private
FNombreClase: string;
public
property NombreClase: string
read FNombreClase write FNombreClase;
end;

implementation

{$R *.dfm}

uses
SysUtils, Dialogs;

function CompararNombres(item1, item2: Pointer): integer;
begin
Result := CompareText(TMiClase(item1).NombreClase,
TMiClase(item2).NombreClase);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
FMiLista := TList.Create;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FMiLista.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
unaClase, otraClase: TMiClase;
begin
unaClase := TMiClase.Create;
unaClase.NombreClase := 'Zaragoza';

otraClase := TMiClase.Create;
otraClase.NombreClase := 'Abecedario';

FMiLista.Add(unaClase);
FMiLista.Add(otraClase);

FMiLista.Sort(@CompararNombres);

for i := 0 to FMiLista.Count-1 do
begin
// Mostrará primero Abecedario y luego Zaragoza
ShowMessage( TMiClase(FMiLista.Items[i]).NombreClase );
end;
end;

end.



¿No? :)

La errata parece estar en el puntero a la función que se pasa como parámetro al método "Sort" de "Tlist":


List1.Sort(@CompareText);


Cuando debería ser:


List1.Sort(@CompareNames);

roman
18-09-2006, 21:40:21
El ejemplo de la ayuda no compila porque el operador as no es aplicable.

// Saludos

dec
18-09-2006, 21:46:57
Hola,

Vale, pero, tampoco compilaría aunque hicieras el "cast" como lo hago yo más arriba: porque el puntero no se pasa a la función correcta, y eso es una errata de la ayuda o me equivoco. Por otro lado todavía no tengo claro por qué el operador "as", como dices, no es aplicable...

Desde luego, si quitamos eso y la posible errata el código que he expuesto compila y funciona como se espera. O me equivoco... :confused:

maeyanes
18-09-2006, 21:50:35
No aplica el operador as por que Pointer no es una clase, es solo un tipo de datos y este operador es un operador de clases.



Saludos...

seoane
18-09-2006, 21:51:06
Después de de la primera respuesta de elcigarra me disponía a hacer un ejemplito, algo sencillo, pero tuve que atender a otro asunto durante un rato. Cuando vuelvo le doy a "Recargar" y me encuentro con todo esto :eek: . Así no hay forma de responder, si no te das prisa te pisan la respuesta :D

maeyanes
18-09-2006, 21:56:08
Bien dicen que "camarón que se duerme..." :D

dec
18-09-2006, 21:56:11
Hola,


No aplica el operador as por que Pointer no es una clase, es solo un tipo de datos y este operador es un operador de clases.


¿Cómo es que se pone en el ejemplo de la ayuda de Delphi, entonces? Aunque, si se piensa en la errata que parece contener... no sería extraño que algo más estuviera también equivocado, incluso cuando se mencione esto:


The following code sorts the objects in a list in alphabetical order based on their names. It assumes that the list contains only component references.


Que alguien me lo explique, por favor. :D


Después de de la primera respuesta de elcigarra me disponía a hacer un ejemplito, algo sencillo, pero tuve que atender a otro asunto durante un rato. Cuando vuelvo le doy a "Recargar" y me encuentro con todo esto :eek: . Así no hay forma de responder, si no te das prisa te pisan la respuesta :D


Sí, pero, cada uno aporta lo suyo, unos más modestamente que otros (hablo por mí). Por ejemplo, al ver que te habías unido al Hilo he pensado, ahí está Seoane con la solución del caso. :D :D

Por cierto, voy a ver si me preparo algo para cenar... y ceno... :D: D

roman
18-09-2006, 21:57:29
No aplica el operador as por que Pointer no es una clase, es solo un tipo de datos y este operador es un operador de clases.


Así es. Si no entiendo por qué tanto brinco estando el suelo tan parejo. :)

¿Hay que defender la ayuda de Delphi? :confused:

// Saludos

maeyanes
18-09-2006, 21:58:43
¿Cómo es que se pone en el ejemplo de la ayuda de Delphi, entonces? Aunque, si se piensa en la errata que parece contener... no sería extraño que algo más estuviera también equivocado, incluso cuando se mencione esto:


Que alguien me lo explique, por favor. :D


Pues la única explicación que encuentro es que el que elaboró este ejemplo no lo compiló para probar que funcionara... jejeje



Saludos...

dec
18-09-2006, 22:00:42
Hola,


¿Hay que defender la ayuda de Delphi? :confused:


¿De qué estamos hablando? No se trata de defender la ayuda de Delphi, ¿cómo se te ha ocurrido algo así? Se trata de que en la ayuda, en este caso, se puede ver una solución "lógica" a lo que nos ocupa. A lo menos a mí me lo parece. Ahora bien, parece que el ejemplo de la ayuda tiene algunos errores... o erratas... o algo... natural, comprensible, humano.

De hecho mi primera respueste fue que se implementase un método de ordenación en una clase derivada de "TList",... porque me parecía lo más lógico del mundo... claro, que, yo no contaba (sabía) que "TList" ya implementa un método "Sort".

Ahora bien, ¿se trata de utilizar el método "Sort", verdad? Pues entonces, puede hacerse siguiendo la ayuda de Delphi aparte y/o a pesar del ejemplo. Lo demuestro arriba, ¿por eso quiero defender la ayuda de Delphi?

Y ahora sí que me voy a cenar... por cierto... :D :D

roman
18-09-2006, 22:05:47
¿De qué estamos hablando?

Eso a mi me gustaría saber. Tú citaste un ejemplo de Delphi y yo me limité a señalar que es erróneo y que el código de Marcos estaba mejor. Todo lo demás no lo entiendo.

// Saludos

dec
18-09-2006, 22:26:42
Hola,


Eso a mi me gustaría saber. Tú citaste un ejemplo de Delphi y yo me limité a señalar que es erróneo y que el código de Marcos estaba mejor. Todo lo demás no lo entiendo.


Yo indiqué la ayuda de Delphi en primer lugar, el ejemplo vino luego. Lo que parece ser erróneo es el ejemplo de la ayuda de Delphi, por eso no entiendo cómo lo comparas con el código de Marcos: no son comparables, sencillamente, el del ejemplo no compila, no funciona.

Ahora bien, siguiendo la ayuda... fijándose uno en el ejemplo... y dándose cuenta del posible error en este, todavía cree que hay que aprovechar el método "Sort" de la clase "TList", y así es que todo va bien, es decir, puede utilizarse sin problemas.

Ahora bien, el código de Marcos y el que yo mismo he propuesto (siguiendo la ayuda de Delphi) sí que podrían compararse, a lo menos en cuanto a que ambos consigue el objetivo. ¿Tú con cuál te quedas Román? Y, sobre todo, ¿por qué con uno y no con otro? ;)

Edito: Ahora me doy cuenta de que no había mirado bien código de Marcos... ¡es el mismo que yo he propuesto! ¡es justo eso! Hum... me parece que he metido la pata y no sé bien cómo ni de qué manera, ¿o me equivoco? Decirme que no, por favor. :D

maeyanes
18-09-2006, 22:29:43
Bueno, mi ejemplo es precisamente la función que se le pasa al método Sort, ahora, tal vez me faltó especificar como mandar a llamar al método Sort usando la función creada con anterioridad...

Creo que de ahí un poco la confusión...



Saludos...

roman
18-09-2006, 22:29:50
Pues tú sabrás de qué hablas. Yo no

// Saludos

dec
18-09-2006, 22:34:48
Hola,

Efectivamente, hay confusión, y la culpa es mía, que me confundieron las palabras de Román:


Ejemplo que, me parece, no puede compilar. Mejor hacer como Marcos.


Yo debí mirar el código de Marcos por encima, no caí en que se trataba del código correcto, y así me puse a defender mi código y no el de Marcos, basándome, por supuesto, en que mi código seguía la ayuda de Delphi, siguiera o no el ejemplo... Claro, por medio también ha estado que, precisamente el ejemplo que nos ocupa de la ayuda de Delphi está equivocado, contiene una errata... ¿y cuántos ejemplos de la ayuda de Delphi han visto que contengan erratas? Yo creo que este es el primero que veo...

Pido disculpas a quienes se pudieran sentir molestos o extrañados. Procuraré estar más vivo la próxima vez. :o

dec
18-09-2006, 22:48:22
Hola,

Joroba, yo que esperaba una respuesta del tipo "No te preocupes David", o "A todos nos pasa David, no te apures", o "No hace falta pedir disculpas, hombre", o "¿Qué demonios cenaste, si puede saberse?"... Cómo sois... hay que veros... :eek: :) :D

maeyanes
18-09-2006, 22:49:40
No te preocupes David...

:D :D :D

dec
18-09-2006, 22:51:47
Hola,

Ah, esto ya es otra cosa, ¿ves? Así sí. Gracias Marcos. ;)

Por cierto, buscamos el usuario número 100 de Loturak (http://www.loturak.es/loturakitas)... :eek: :eek: :eek: :D

maeyanes
18-09-2006, 22:55:45
Listo, ya somos 100 :D :D :D

dec
18-09-2006, 22:57:41
Hola,

¡Muchas gracias! Esperamos que te sea útil. Pásate por la taberna (http://www.clubdelphi.com/foros/forumdisplay.php?s=&daysprune=&f=40) y pide algo que nosotros lo pagamos... :eek: :eek: :) :D :)

pescriba
23-01-2009, 13:07:51
Una forma mas simple de solucionar el problema


function Compare(Item1: Pointer; Item2: Pointer): Integer;
begin
if TMiClase(Item1).Propiedad > TMiClase(Item2).Propiedad then
Result := 1
else
if TMiClase(Item1).Propiedad = TMiClase(Item2).Propiedad then
Result := 0
else
Result := -1
end;



Saludos...[/QUOTE]

maeyanes
24-01-2009, 00:22:34
Alguién anda atrasado 3 años... :D :D :D