dicas show delphi

DICAS

Visite a biblioteca de dicas da comunidade.

Saiba mais
sombra
Artigos Show Delphi

ARTIGOS

Abordagens detalhadas sobre assuntos diversos.

Saiba mais
sombra
iniciantes show delphi

INICIANTES

Aprenda a programar de um modo simples e fácil.

Saiba mais
sombra
downloads show delphi

DOWNLOADS

Acesse os materiais exclusivos aos membros.

Saiba mais
sombra
voltar

PARA QUEM GOSTA DE DELPHI

Comparação de Strings com o Delphi

Para um correto entendimento sobre o problema é recomendável ler sobre
longest common subsequence (LCS) problem na Wikipedia.

Depois de ler o artigo da Wikipedia sobre, Yanniel obteve uma visão geral do problema e decidiu implementar uma classe Delphi para fazer o truque de comparação de strings, que é a base para a comparação de arquivos de texto.

No exemplo temos duas strings para serem comparadas, onde vamos destacar em azul os caracteres adicionados à primeira string e em vermelho os caracteres removidos dela. Os caracteres comuns (inalterados) manterão a cor padrão.

comparacao-string

A classe de comparação irá parecer com isso:

1
2
3
4
5
6
7
8
9
10
11
type
  TDiff = record
    Character: Char;
    CharStatus: Char;  //Possible values: [+, -, =]
  end;
 
  TStringComparer = class
  ……………
  public
    class function Compare(aString1, aString2: string): TList<TDiff>;
  end;

Quando você chama TStringComparer.Compare, uma lista genérica de registros TDiff é criada. Um registro TDiff contém um caractere e se esse caractere foi adicionado ( CharStatus = ‘+’), removido ( CharStatus = ‘-‘) ou inalterado ( CharStatus = ‘=’) em ambas as sequências sob comparação.

Vamos colocar duas edits ( Edit1 , Edit2 ), uma edição rica ( RichEdit1 ) e um botão ( Button1 ) em um formulário Delphi. Para destacar as diferenças, coloque o seguinte código no evento OnClick do botão:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
procedure TForm1.Button1Click(Sender: TObject);
var
  Differences: TList<TDiff>;
  Diff: TDiff;
begin
  //Yes, I know...this method could be refactored ;-)
  Differences:= TStringComparer.Compare(Edit1.Text, Edit2.Text);
  try
    RichEdit1.Clear;
    RichEdit1.SelStart:= RichEdit1.GetTextLen;
    for Diff in Differences do
      if Diff.CharStatus = '+' then
      begin
        RichEdit1.SelAttributes.Color:= clBlue;
        RichEdit1.SelText := Diff.Character;
      end
      else if Diff.CharStatus = '-' then
      begin
        RichEdit1.SelAttributes.Color:= clRed;
        RichEdit1.SelText:= Diff.Character;
      end
      else
      begin
        RichEdit1.SelAttributes.Color:= clDefault;
        RichEdit1.SelText:= Diff.Character;
      end;
  finally
    Differences.Free;
  end;
end;

O programa irá fazer parecido com a imagem abaixo:
exemplo-comparacao-string

Abaixo segue um exemplo de implementação, lógico que diversas melhorias podem ser implementadas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
unit StringComparison;
 
interface
 
uses
Math, Generics.Collections;
 
type
TDiff = record
Character: Char;
CharStatus: Char;  //Possible values: [+, -, =]
end;
 
TStringComparer = class
strict private
type TIntArray = array of array of Integer;
class function LCSMatrix(X, Y: string): TIntArray;
class procedure ComputeDifferences(aLCSMatrix: TIntArray;
X, Y: string;
i, j: Integer;
aDifferences: TList<TDiff>);
public
class function Compare(aString1, aString2: string): TList<TDiff>;
end;
 
implementation
 
{ TStringComparer }
 
class function TStringComparer.LCSMatrix(X, Y: string): TIntArray;
var
m, n,
i, j: Integer;
begin
m:= Length(X);
n:= Length(Y);
 
//We need one extra column and one extra row to be filled with zeroes
SetLength(Result, m + 1, n + 1);
 
//First column filled with zeros
for i := 0 to m do
Result[i, 0] := 0;
 
//First row filled with zeros
for j:= 0 to n do
Result[0, j]:= 0;
 
//Storing the lengths of the longest common subsequences
//between prefixes of X and Y
for i:= 1 to m do
for j:= 1 to n do
if X[i] = Y[j] then
Result[i, j] := Result[i-1, j-1] + 1
else
Result[i, j]:= Max(Result[i, j-1], Result[i-1, j]);
end;
 
class procedure TStringComparer.ComputeDifferences(aLCSMatrix: TIntArray;
X, Y: string;
i, j: Integer;
aDifferences: TList<TDiff>);
var
CharDiff: TDiff;
begin
if (i > 0) and (j > 0) and (X[i] = Y[j]) then
begin
ComputeDifferences(aLCSMatrix, X, Y, i-1, j-1, aDifferences);
CharDiff.Character:= X[i];
CharDiff.CharStatus:= '=';   //The character did not change
aDifferences.Add(CharDiff);
end
else
if (j > 0) and ((i = 0) or (aLCSMatrix[i,j-1] >= aLCSMatrix[i-1,j])) then
begin
ComputeDifferences(aLCSMatrix, X, Y, i, j-1, aDifferences);
CharDiff.Character:= Y[j];
CharDiff.CharStatus:= '+'; //The character was added
aDifferences.Add(CharDiff);
end
else if (i > 0) and ((j = 0) or (aLCSMatrix[i,j-1] < aLCSMatrix[i-1,j])) then
begin
ComputeDifferences(aLCSMatrix, X, Y, i-1, j, aDifferences);
CharDiff.Character:= X[i];
CharDiff.CharStatus:= '-'; //The character was removed
aDifferences.Add(CharDiff);
end;
end;
 
//This is a factory method
class function TStringComparer.Compare(aString1, aString2: string): TList<TDiff>;
var
Matrix: TIntArray;
begin
Result:= TList<TDiff>.Create;
Matrix:= LCSMatrix(aString1, aString2);
ComputeDifferences(Matrix,
aString1, aString2,
Length(aString1), Length(aString2),
Result);
end;
 
end.

Baixe aqui os fontes do exemplo do post
[download id=”3107″]

Dúvidas ou sugestões? Deixe o seu comentário!

Baseado no post: http://www.yanniel.info/2012/01/lcs-string-comparison-in-delphi.html

  • Giovani Da Cruz
  • 0 comentários
  • 26 de março de 2019

Deixe um comentário

Ir ao topo

© 2024 Infus Soluções em Tecnologia - Todos os Direitos Reservados