Recentemente um colega delpheiro me perguntou como ordenar um memo não pelo seu conteúdo, mas por alguma regra especial.
No caso dele, ele tinha no memo várias strings separadas por ":" com números do outro lado. Algo assim:
A:3
B:5
C:1
Devendo ficar:
C:1
A:3
B:5
Para isso podemos usar a função CustomSort do memo, passando como argumento uma função. Essa é uma função especial que aceita uma lista como parâmetro, dois índices da lista e retorna um integer. Assim ela pode comparar dois itens da lista e retornar 1 se o primeiro for maior, 0 se os itens forem iguais ou -1 se o segundo for maior.
Essa função é que fará todo o trabalho de comparação, portanto você decide como os itens serão comparados. A função CustomSort saberá que deve chamar a sua função para decidir, na varredura, qual item é maior porque você passará o nome da sua função, como se fosse um delegate ou ponteiro para função, como argumento para a função customsort.
Os memos podem ser usados como dictionaries, ou como arquivos ini, eles podem ter pares de namve/value, e para isso você define a propriedade NameValueSeparator. Definindo esta propriedade como ":" os valores são automaticamente separados em duas partes.
O código ficou como abaixo:
//crio uma function inline que compara só dois valores e diz qual é o maior
//ela é usada automaticamente para comparar os valores 2 a 2 dentro da função
//customsort do stringlist e ordenar a parada toda
function compara(List: TStringList; Index1, Index2: Integer): Integer;
var val1: integer;
val2: integer;
begin
//defino que o separador e chave / valor NameValueSeparator é ':', a string separadora.
List.NameValueSeparator := ':';
val1 := StrToInt( List.ValueFromIndex[Index1]);
val2 := StrToInt( List.ValueFromIndex[Index2]);
//quando você coloca o delimitador de um tstringlist você pode separar ele em key e value
//essa função pode ser anonima
//se o valor do indice 1 for maior que o 2 retorna 1
if(val1 > val2) then
Result := 1
//se for menor retorna -1
else if(val2 > val1) then
Result := -1
else
//se for igual retorna zero
Result := 0;
//esses resultados -1, 0 e 1 são o padrão de todos os comparers
end;
procedure TForm1.Button1Click(Sender: TObject);
//crio um stringlist temporário para guardar o conteudo ordenado
var str: TStringList;
begin
str := TStringList.Create;
//mando o conteudo do memo para o stringlist
str.AddStrings(Memo1.Lines);
//mando ordenar passando como parâmetro a função ordenadora (existem
//funções que aceitam outras funções como parâmetro, não o retorno dela, mas seu escopo, ela será executada internamente)
str.CustomSort( compara );
//limpa o memo1
Memo1.Clear;
//adiciona o valor ja ordenado
Memo1.Lines.AddStrings(str);
//destroi o stringlist
str.Free;
end;
Have fun :)
Bom dia.
ResponderExcluirParabéns pelo post.
Sou estudante de programação pelo curso adv, www.cursoadv.com.br
Muito obrigado pela dica, é muito bom contar com esse material complementar.