Question

I must compare 2 stringlist , I wonder if the search the first stringlist inside the second stringlist is the only or the recommended version to execute this problem

My code would go like this

var
  aFirstStrList: TStringList ;
  aSecondStringList: TStringList; 
  MissingElement_firstElement_not_inside_second: TStringList;
  MissingElement_SecondElement_not_inside_First: TStringList;

...

for i := 0 to aFirstStrList.Count - 1 do
begin
  if aSecondStringList.IndexOf(aFirstStrList[i] < 0 ) then
  begin
    // react on not found elements 
    ....
    MissingElement_firstElement_not_inside_second.add(...);
  end;
end;
// and now same code just opposite search direction .... 
....
Was it helpful?

Solution

Instead of using IndexOf, sort both lists before, to prevent searching the whole list at every cycle. Furthermore, it is possible to achieve this in one single loop.

Assuming you want the results in two separate string lists, try the following:

procedure CompareStringLists(List1, List2: TStringList;
  Missing1, Missing2: TStrings);
var
  I: Integer;
  J: Integer;
begin
  List1.Sort;
  List2.Sort;
  I := 0;
  J := 0;
  while (I < List1.Count) and (J < List2.Count) do
  begin
    if List1[I] < List2[J] then
    begin
      Missing2.Add(List1[I]);
      Inc(I);
    end
    else if List1[I] > List2[J] then
    begin
      Missing1.Add(List2[J]);
      Inc(J);
    end
    else
    begin
      Inc(I);
      Inc(J);
    end;
  end;
  for I := I to List1.Count - 1 do
    Missing2.Add(List1[I]);
  for J := J to List2.Count - 1 do
    Missing1.Add(List2[J]);
end;

Usage:

procedure TForm1.Button1Click(Sender: TObject);
var
  List1: TStringList;
  List2: TStringList;
begin
  List1 := TStringList.Create;
  List2 := TStringList.Create;
  try
    List1.CommaText := 'A, C, F, G, H, K, L, M, N, O, Q, R';
    List2.CommaText := 'C, D, E, F, J, P, Q, S, T, U, V, W';
    Memo1.Lines.Assign(List1);
    Memo2.Lines.Assign(List2);
    CompareStringLists(List1, List2, Memo3.Lines, Memo4.Lines);
  finally
    List2.Free;
    List1.Free;
  end;
end;

OTHER TIPS

The best performance:
Sort input string lists
Compare with algorithm similar to merge sorted lists(there you will find what is missing in each list)

Simpler but slower:
Copy stringlists to result stringlists
One loop for first string list (use reversed loop for this for Count-1 downto 0 do)
Search same string in second, if found - delete from both lists
Differences will remain in string lists

You have to be careful with that implementation of CompareStringLists. By default the Sort routine of TStringList will sort case insensative but the Comparison used is case-sensative, the up shot being if you have any mixed case in your lists you will get a blowout of the supposed miss-matches.

Either need to set the sorts to be case-sensative by

List1.CaseSensative := true ;
List1.Sort ;
List2.CaseSensative := true ;
List2.Sort ;

OR

Make the comparisons case-insensative

if UpperCase(List1[I]) < UpperCase(List2[J]) then

and

else if UpperCase(List1[I]) > UpperCase(List2[J]) then

respectively.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top