我知道如何使用dupignore从TStringList中删除重复的字符串以用于排序的Tstringlist。
CallData := TStringList.Create;
CallData.Sorted := True;
Call.Duplicates := dupIgnore;
但在我的情况下,字符串不能排序。
当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;
还有更好的方法吗?
答案 0 :(得分:6)
以下是我将如何处理此问题:
如果要删除大量重复项,则从字符串列表中重复删除会影响上述性能。这是因为要删除的每个项目都会导致后面的项目向下移动一个索引。您可以通过复制到新列表而不是删除就地来避免这种情况。
或者,你可以这样操作:
Count
的变量初始化为零。 Count
,然后递增Count
。 Count
个元素。 字典的要点是查找是O(1)操作,因此第二种算法具有O(n)时间复杂度。
答案 1 :(得分:2)
我会使用trickery,通过排序和未排序的列表。像这样:
for row in try! db.prepare("SELECT * FROM things") {
let value = row[4]
print(value) //This logs "Optional(7)" or "Optional(1.2)" etc.
switch value{
case let double as Double:
print("Double: \(double)") //This never gets called...
case let int as Int:
print("Int: \(int)") //This never gets called
default:
return 0 //This always gets called
}
}
答案 2 :(得分:1)
function compareobjects
(list : Tstringlist;
index1 : integer;
index2 : integer
) : integer;
begin
if index1 = index2 then
result := 0
else
if integer(list.objects[index1]) < integer(list.objects[index2]) then
result := -1
else
result := 1;
end;
begin
Try
y := TStringList.create;
y.Sorted := true;
y.Duplicates := dupignore;
f := TStreamReader.create('c:\106x\q47780823.bat');
i := 0;
while not f.EndOfStream do
begin
inc(i);
line := f.readline;
y.Addobject(line,tobject(i));
end;
y.Sorted := false;
y.CustomSort(compareobjects);
for i := 0 to y.count - 1 do
WriteLn(y[i]);
Finally
f.free;
y.free;
End;
readln;
end.
我跟踪行号(i
)并通过强制转换为对象来为其分配;按照以前的方式对列表进行排序并删除重复项,然后使用对象的自定义排序对其进行取消排序。