quarta-feira, 31 de outubro de 2012

Como Ordenar uma Lista de Objetos (TObjectList)

Ordenação  de TObjectList

Muitas vezes utilizamos listas de objetos (TObjectList) para agrupar clientes, contatos, produtos, etc.
Pode ser que os dados sejam adicionados a lista sem uma ordenação lógica, ordenação esta que pode vir a ser necessária.
A classe TObjectList possui o método Sort que possui a seguinte assinatura:

procedure Sort(Compare: TListSortCompare);

O parâmetro Compare é do tipo TListSortCompare que deve ser uma função com a seguinte assinatura

TListSortCompare = function (Item1, Item2: Pointer): Integer;

Como vocês podem ver, para ordenar a lista será necessário criar uma função de ordenação utilizando a regra que desejarmos.

Exemplo de função de ordenação

Para exemplificar vou criar uma classe Item, uma lista de Itens(TItemList) e duas funções de ordenação.


type
  TItem = class(TObject)
  private
    FName: string;
    FID: Integer;
    procedure SetID(const Value: Integer);
    procedure SetName(const Value: string);
  public
    property ID   : Integer read FID write SetID;
    property Name : string read FName write SetName;
  end;

  TItemList = class(TObjectList)
  public
    function Add(AObject: TItem): Integer;
  end;

function SortAscending(Item1, Item2: Pointer): Integer;
var Obj1 : TItem;
    Obj2 : TItem;
begin
  Obj1 := TItem(Item1);
  Obj2 := TItem(Item2);
  if Obj1.ID > Obj2.ID then
    Result := +1
  else
    if Obj1.ID < Obj2.ID then
      Result := -1
    else
      Result := 0;
end;

function SortDescending (Item1, Item2: Pointer): Integer;
var Obj1 : TItem;
    Obj2 : TItem;
begin
  Obj1 := TItem(Item1);
  Obj2 := TItem(Item2);
  if Obj1.ID > Obj2.ID then
    Result := -1
  else
    if Obj1.ID < Obj2.ID then
      Result := +1
    else
      Result := 0;
end;

Agora um exemplo de utilização das classes e funções. Será utilizado um laço para gerar aleatoriamente 10 ID diferentes para preencher um componente Memo na ordem de geração e depois em Ordem Crescente e Decrescente.

var Item : TItem;
    List : TItemList;
    idx  : Integer;
    ID   : Integer;
begin
  Memo1.Lines.Clear;
  Memo1.Lines.Add('Ordem de Geração');
  List := TItemList.Create;
  for idx := 1 to 10 do
  begin
    ID := Random(99) + 1;
    Item := TItem.Create;
    Item.ID := ID;
    Item.Name := Format('Item%.3d', [ID]);
    List.Add(Item);
    Memo1.Lines.Add(Format('ID=%.3d', [Item.ID]));
  end;

  Memo1.Lines.Add('=====');
  Memo1.Lines.Add('Ordem Ascendente');
  List.Sort(SortAscending);
  for idx := 0 to List.Count -1 do
  begin
    Item := List[idx] AS TItem;
    Memo1.Lines.Add(Format('ID=%.3d', [Item.ID]));
  end;

  Memo1.Lines.Add('=====');
  Memo1.Lines.Add('Ordem Descendente');
  List.Sort(SortDescending);
  for idx := 0 to List.Count -1 do
  begin
    Item := List[idx] AS TItem;
    Memo1.Lines.Add(Format('ID=%.3d', [Item.ID]));
  end;
end;


Este código irá gerar uma saída semelhante a esta:
Ordem de Geração
ID=063
ID=090
ID=078
ID=009
ID=067
ID=026
ID=045
ID=083
ID=027
ID=073
=====
Ordem Ascendente
ID=009
ID=026
ID=027
ID=045
ID=063
ID=067
ID=073
ID=078
ID=083
ID=090
=====
Ordem Descendente
ID=090
ID=083
ID=078
ID=073
ID=067
ID=063
ID=045
ID=027
ID=026
ID=009

Como vocês viram é simples gerar a função de ordenação, seria possível ordenar por data, nome ou qualquer outra propriedade presente nos Objetos da Lista. Até a próxima :D

0 comentários:

Blogger Template by Clairvo