Compare to Stringlist
Asked Answered
S

3

12

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 .... 
....
Softboiled answered 27/7, 2013 at 7:29 Comment(1)
It depends on ... please define "difference". Just think about a;b and a;a. What result would you like to get in this case?Pastoral
B
13

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;
Burge answered 27/7, 2013 at 8:5 Comment(0)
K
1

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

Kneehigh answered 27/7, 2013 at 8:0 Comment(0)
P
0

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.

Phallic answered 21/3, 2017 at 9:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.