我有一些文件(3-5)需要比较:
文件1.txt有100万个字符串
文件2.txt有1000万个字符串
文件3.txt有500万个字符串
所有这些文件都与文件keys.txt(万字符串)进行比较。如果当前打开的文件中的行与keys.txt中的行相同,请将此行写入output.txt(我希望您理解我的意思)。
现在我有:
function Thread.checkKeys(sLine: string): boolean;
var
SR: TStreamReader;
line: string;
begin
Result := false;
SR := TStreamReader.Create(sKeyFile); // sKeyFile - Path to file keys.txt
try
while (not(SR.EndOfStream)) and (not(Result))do
begin
line := SR.ReadLine;
if LowerCase(line) = LowerCase(sLine) then
begin
saveStr(sLine);
inc(iMatch);
Result := true;
end;
end;
finally
SR.Free;
end;
end;
procedure Thread.saveStr(sToSave: string);
var
fOut: TStreamWriter;
begin
fOut := TStreamWriter.Create('output.txt', true, TEncoding.UTF8);
try
fOut.WriteLine(sToSave);
finally
fOut.Free;
end;
end;
procedure Thread.updateFiles;
begin
fmMain.flDone.Caption := IntToStr(iFile);
fmMain.flMatch.Caption := IntToStr(iMatch);
end;
用
循环 fInput := TStreamReader.Create(tsFiles[iCurFile]);
while not(fInput.EndOfStream) do
begin
sInput := fInput.ReadLine;
checkKeys(sInput);
end;
fInput.Free;
iFile := iCurFile + 1;
Synchronize(updateFiles);
因此,如果我将这3个文件与文件key.txt进行比较,则需要大约4个小时。如何减少比较时间?
答案 0 :(得分:7)
一个简单的解决方案是使用关联容器来存储密钥。这可以提供有效的查找。
在Delphi中,您可以使用TDictionary<TKey,TValue>
中的Generics.Collections
。此容器的实现散列密钥并提供O(1)查找。
像这样声明容器:
Keys: TDictionary<string, Boolean>;
// doesn't matter what type you use for the value, we pick Boolean since we
// have to pick something
像这样创建并填充它:
Keys := TDictionary<string, Integer>.Create;
SR := TStreamReader.Create(sKeyFile);
try
while not SR.EndOfStream do
Keys.Add(LowerCase(SR.ReadLine), True);
// exception raised if duplicate key found
finally
SR.Free;
end;
然后你的检查功能变为:
function Thread.checkKeys(const sLine: string): boolean;
begin
Result := Keys.ContainsKey(LowerCase(sLine));
if Result then
begin
saveStr(sLine);
inc(iMatch);
end;
end;
答案 1 :(得分:0)
首先,您应该将Keys.txt加载到例如TStringList中。不要每次从文件中读取密钥。在如此高计数循环中的第二个你不应该使用过程/函数调用你应该内联所有检查。
这样的事情:
Keys:=TStringList.Create;
Keys.LoadFromFile('keys.txt');
fInput := TStreamReader.Create(tsFiles[iCurFile]);
fOut := TStreamWriter.Create('output.txt', true, TEncoding.UTF8);
while not(fInput.EndOfStream) do
begin
sInput := fInput.ReadLine;
if Keys.IndexOf(sInput)>=0 then
begin
fOut.WriteLine(sInput);
inc(iMatch);
end;
end;
fInput.Free;
fOut.Free;
iFile := iCurFile + 1;
Synchronize(updateFiles);
Keys.Free;