Ich würde folgendes vorschlagen:
Delphi-Quellcode:
function RemoveCharsFromString(const AStr, CharsToRemove: string): string;
var
i, NewLength: Integer;
begin
SetLength(Result, AStr);
NewLength := 0;
for i := 1 to Length(AStr) do
begin
if Pos(CharsToRemove, AStr[i]) = 0 then
begin
Result[NewLength] := AStr[i];
inc(NewLength);
end;
end;
SetLength(Result, NewLength);
end;
Das ist für mich der beste Kompromiss aus Geschwindigkeit, Funktionalität und Einfachheit. Wenn man will, kann man das Pos natürlich auch noch durch eine eigene Schleife ersetzen.
Wenn man unbedingt noch mehr rausholen will:
Zu Sets bzw. Array of Bool[Char] ist zu sagen, dass es wohl schon einen Sinn haben dürfte, weshalb Set auf 256 Elemente begrenzt ist. Mit jedem weiteren Element wächst auch der Speicherverbrauch. Bei WideChar belegt
Array of Bool
bereits 65 Kilobyte. Würde man statt Bools einzelne Bits verwenden wie bei
Set
, sind es immer noch 8 Kilobyte. Das ist zu groß um komplett in den CPU-Cache geladen zu werden. Würde man sequenziell durch den Bereich durchlaufen, wäre das zwar kein Problem, aber Sets sind prinzipbedingt Random
Access. Würde mich nicht wundern, wenn es schneller wäre, einfach in einer Schleife durch die zu löschenden Elemente zu gehen und immer zu vergleichen (wie in meinem Code), solange es eine überschaubare Anzahl Zeichen ist, die entfernt werden soll.
@Namenloser:
Hast du denn einmal die von dir vorgeschlagene Funktion laufen lassen?
Wenn "JA", dann hättest du merken müssen
1) In der ersten Zeile
SetLength(Result, AStr);
sollte eine Fehlermeldung kommen, dass man der Länge eines Strings keinen String zuweisen kann.
2) Bei
if Pos(CharsToRemove, AStr[i]) = 0 then
sollte dir aufgefallen sein, dass du die Position eines Strings innerhalb eines Chars abfragst, was natürlich immer 0 ergibt.
3) Bei
Delphi-Quellcode:
Result[NewLength] := AStr[i];
inc(NewLength);
sollte es scheppern, weil du Result[0] ein Char zuweisen willst.
Zu
Zitat:
Das ist für mich der beste Kompromiss aus Geschwindigkeit, Funktionalität und Einfachheit.
Die Fragestellung in #1 war
Zitat:
Was ist die SCHNELLSTE Methode, um aus einem String alle Zeichen eines anderen Strings zu entfernen?
Es war also weder ein Kompromiss noch Funktionalität noch Einfachheit gefragt, sondern ausschließlich Schnelligkeit.
Sorry, falls du dich angegriffen fühlen solltest; aber wenn jemand einen Code der gleich 3 so offensichtliche Fehler enthält und so nicht einmal kompilierbar ist, als "Besten Kompromiss" vorstellt, dann juckt es mich schon in den Fingern.
Ich habe, nachdem ich die Fehler in deinem Code korrigiert habe, beide Funktionen laufen lassen, deine aus #28 und meine aus #19.
Als String, aus dem Zeichen entfernt werden sollen, habe ich den letzten Absatz deines Beitrages #28
und als String mit zu entfernenden Zeichen deinen Nick "Namenloser" benutzt.
Die Ergebnisse waren für mich nicht überraschend.
So habe ich getestet;
Delphi-Quellcode:
PROCEDURE TMain.Test;
FUNCTION TimeStamp:Int64;
asm
rdtsc
{$IFDEF CPUX64}
shl rdx,32
or rax,rdx
{$ENDIF}
end;
const
S='
Zu Sets bzw. Array of Bool[Char] ist zu sagen, dass es wohl schon einen '+
'
Sinn haben dürfte, weshalb Set auf 256 Elemente begrenzt ist. Mit jedem '+
'
weiteren Element wächst auch der Speicherverbrauch. Bei WideChar belegt '+
'
Array of Bool bereits 65 Kilobyte. Würde man statt Bools einzelne Bits '+
'
verwenden wie bei Set , sind es immer noch 8 Kilobyte. Das ist zu groß '+
'
um komplett in den CPU-Cache geladen zu werden. Würde man sequenziell '+
'
durch den Bereich durchlaufen, wäre das zwar kein Problem, aber Sets '+
'
sind prinzipbedingt Random Access. Würde mich nicht wundern, wenn es '+
'
schneller wäre, einfach in einer Schleife durch die zu löschenden '+
'
Elemente zu gehen und immer zu vergleichen (wie in meinem Code), solange '+
'
es eine überschaubare Anzahl Zeichen ist, die entfernt werden soll.';
R='
Namenloser';
Res:
Array[Boolean]
of String=('
Ergebnisse verschieden','
Ergebnisse gleich');
var
T0,T1,T2:Int64; S1,S2:
String;
begin
T0:=TimeStamp;
S1:=RemoveCharsFromString(S,R);
T1:=TimeStamp;
S2:=RemoveChars(S,R);
T2:=TimeStamp;
Dec(T2,T1);
Dec(T1,T0);
ShowMessage(Res[S1=S2]+#13+IntToStr(T1)+#13+IntToStr(T2));
end;