Einzelnen Beitrag anzeigen

Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#19

AW: Dateiliste gefiltert erstellen

  Alt 25. Aug 2023, 00:40
Hallo DieDolly, ich bin mir nicht sicher ob das hier schneller ist aber so mache ich es.
Delphi-Quellcode:
program Project12;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.Classes,
  System.SysUtils,
  Generics.Collections;

type
  TTrieFilter = class
  private
    FChildren: TObjectDictionary<Char, TTrieFilter>;
    FIsWord: Boolean;
  public
    constructor Create;
    destructor Destroy; override;
    procedure AddWord(const Word: string);
    function ContainsWord(const Word: string): Boolean;
  end;

constructor TTrieFilter.Create;
begin
  FChildren := TObjectDictionary<Char, TTrieFilter>.Create([doOwnsValues]);
  FIsWord := False;
end;

destructor TTrieFilter.Destroy;
begin
  FChildren.Free;
  inherited;
end;

procedure TTrieFilter.AddWord(const Word: string);
var
  Node: TTrieFilter;
  Ch: Char;
  ChildNode: TTrieFilter;
begin
  Node := Self;
  for Ch in Word do
  begin
    if not Node.FChildren.TryGetValue(Ch, ChildNode) then
    begin
      ChildNode := TTrieFilter.Create;
      Node.FChildren.Add(Ch, ChildNode);
    end;
    Node := ChildNode;
  end;

  if not Node.FIsWord then
    Node.FIsWord := True;
end;

function TTrieFilter.ContainsWord(const Word: string): Boolean;
var
  Node: TTrieFilter;
  Ch: Char;
begin
  Node := Self;
  for Ch in Word do
  begin
    if Node.FChildren.ContainsKey(Ch) then
    begin
      Node := Node.FChildren[Ch];
      if Node.ContainsWord(Copy(Word, 2, Length(Word) - 1)) then
        Exit(True)
      else
        Exit(False);
    end;
  end;

  Result := Node.FIsWord;
end;

var
  SLDaten, SLFilter, SLOutput: TStringList;
  Trie: TTrieFilter;
  I: Integer;
begin
  try
    SLFilter := TStringList.Create;
    SLDaten := TStringList.Create;
    SLOutput := TStringList.Create;
    Trie := TTrieFilter.Create;
    try
      // beispielhaft deine filter liste
      SLFilter.Add('Sub1\Sub2\File1.exe');
      SLFilter.Add('FileX.exe');
      SLFilter.Add('Sub1\FileY.exe');

      // hier die klasse mit den filtern befüllen
      for I := 0 to Pred(SLFilter.Count) do
        Trie.AddWord(SLFilter[I]);

      // das hier überspringen und gleich zum filtern weiter
      // stell dir vor das ist deine dateiliste
      // ps: die reihenfolge ist absolute irrelevant
      SLDaten.Add('c:\Hallo DieDolly\Sub1\Sub2\File1.exe');
      SLDaten.Add('WasAuchImmerFileX.exeHierSteht, es triggert');
      SLDaten.Add('\\\Sub2\FileY.exe'); // das ist das einzige was übrig bleibt


      // Filter den input raus
      for I := 0 to Pred(SLDaten.Count) do
        if not Trie.ContainsWord(SLDaten[I]) then
          SLOutput.Add(SLDaten[I]);

      // darstellen was übrig blieb
      for I := 0 to Pred(SLOutput.Count) do
        WriteLn(SLOutput.Strings[I]);

    finally
      SLDaten.Free;
      SLFilter.Free;
      SLOutput.Free;
      Trie.Free;
    end;
    ReadLn;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
Gerne würde ich ein paar brauchbare Benchmark Resultate sehen im Vergleich zu dem THashItem falls Dir meine Klasse gefällt.
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat