5

比較する必要があるいくつかのファイル (3-5) があり
ます。ファイル 1.txt には 100 万の文字列があります。
ファイル 2.txt には 1000 万の文字列があります。
ファイル 3.txt には 500 万の文字列があります。
これらのファイルはすべてファイル keys.txt (10,000 文字列) と比較されます。現在開いているファイルの行が keys.txt の行の 1 つと同じ場合は、この行を 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 時間かかります。比較時間を短縮するには?

4

2 に答える 2

7

簡単な解決策は、連想コンテナーを使用して鍵を保管することです。これにより、効率的な検索が可能になります。

TDictionary<TKey,TValue>Delphi ではfromを使用できます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;
于 2013-10-16T08:56:37.157 に答える
0

まず、Keys.txt を TStringList などにロードする必要があります。ファイルから毎回キーを読み取らないでください。このような高カウント ループの 2 番目では、すべてのチェックをインラインで行う必要があるプロシージャ/関数呼び出しを使用しないでください。

このようなもの:

   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;
于 2013-10-16T08:46:56.037 に答える