从TStringList中删除重复行而不在Delphi中进行排序

Sha*_*deh 6 delphi

我知道如何使用dupignore从TStringList中删除重复的字符串以用于排序的Tstringlist.

CallData := TStringList.Create;
CallData.Sorted := True;
Call.Duplicates := dupIgnore;
Run Code Online (Sandbox Code Playgroud)

但在我的情况下,字符串不能排序.

当TStringList有数十万行时,使用FOR循环查找重复项非常慢(也使用indexOF()).

 if OpenDialog1.Execute then
  begin
    Try
      y := TStringList.create;
      f := TStreamReader.create(OpenDialog1.FileName, TEncoding.UTF8, True);
      while not f.EndOfStream do
      begin
        l := f.ReadLine;
        X.Add(l);
      end;

      g := Tstreamwriter.create('d:\logX.txt', True, TEncoding.UTF8);
      for I := 0 to X.count - 1 do
      begin


          if y.IndexOf(X[I]) = -1 then

          y.Add(X[I]);

      end;

      for j := 0 to y.count - 1 do
        g.WriteLine(y[j]);

    Finally
      f.free;
      y.free;
      g.free;
    End;
  end;
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法?

Dav*_*nan 6

这是我如何处理这个问题:

  1. 创建一个键入字符串的字典.值类型是无关紧要的.
  2. 以相反的顺序遍历字符串列表.
  3. 对于每个字符串,检查它是否在字典中.
  4. 如果它在字典中,则从字符串列表中删除.否则添加到字典中.

如果要删除大量重复项,则从字符串列表中重复删除会影响上述性能.这是因为要删除的每个项目都会导致后面的项目向下移动一个索引.您可以通过复制到新列表而不是删除就地来避免这种情况.

或者,你可以这样操作:

  1. 创建一个键入字符串的字典.值类型是无关紧要的.
  2. 初始化一个名Count为零的变量.
  3. 以正向顺序遍历字符串列表.
  4. 对于每个字符串,检查它是否在字典中.
  5. 如果它在字典中,什么也不做.否则添加到字典中,复制到Count列表的索引中,然后递增Count.
  6. 迭代完成后,调整列表大小以包含Count元素.

字典的要点是查找是O(1)操作,因此第二算法具有O(n)时间复杂度.