AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Schnellstes Entfernen von Chars aus einem String?
Thema durchsuchen
Ansicht
Themen-Optionen

Schnellstes Entfernen von Chars aus einem String?

Ein Thema von PeterPanino · begonnen am 29. Mär 2015 · letzter Beitrag vom 14. Apr 2015
Antwort Antwort
Seite 1 von 2  1 2      
PeterPanino

Registriert seit: 4. Sep 2004
1.472 Beiträge
 
Delphi 10.4 Sydney
 
#1

AW: Schnellstes Entfernen von Chars aus einem String?

  Alt 29. Mär 2015, 16:57
Ich war jetzt im Hintergrund dauernd am Testen, und immer wenn ich eine Antwort schreiben wollte, ist mir ein anderer zuvor gekommen.

DeddyHs Variante ist tatsächlich bei weitem die schnellste, die StringReplace-Variante die mit Abstand langsamste. Bei DeddyH muss man natürlich vorher noch das Charset erstellen.

EDIT: Revidiere mich. Die letzte Variante von Zacherl ist tatsächlich am schnellsten: 10000 Durchgänge in 0,003 Sekunden bei 10 Zeichen langen Strings! Fantastisch!

Geändert von PeterPanino (29. Mär 2015 um 17:07 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.342 Beiträge
 
Delphi 12 Athens
 
#2

AW: Schnellstes Entfernen von Chars aus einem String?

  Alt 29. Mär 2015, 17:05
StringReplace ist nicht das Schnellste, aber sehr einfach.

Außerdem wurden ein paar Fakten vergessen, denn solche Dinge hängen vom Kontext ab.
* Wie lang sind die Strings?
* Was für Zeichen sollen entfernt werden?
* Wieviele Zeichen sollen entfernt werden, so durchschnittlich in Prozenz?
* Was ist schnell? (wie schnell , bzw. oft soll das gemacht werden)
* ...
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.629 Beiträge
 
Delphi 12 Athens
 
#3

AW: Schnellstes Entfernen von Chars aus einem String?

  Alt 29. Mär 2015, 17:22
Die Variante mit dem TSysCharSet funktioniert allerdings nur für AnsiChar (TSysCharSet = set of AnsiChar ) bzw. bei NextGen-Compilern für Zeichen deren Ordnungszahl im Bereich 0..255 liegt.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
PeterPanino

Registriert seit: 4. Sep 2004
1.472 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Schnellstes Entfernen von Chars aus einem String?

  Alt 29. Mär 2015, 17:23
Danke an alle fürs Mitmachen!
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.088 Beiträge
 
Delphi XE2 Professional
 
#5

AW: Schnellstes Entfernen von Chars aus einem String?

  Alt 29. Mär 2015, 18:00
Hier meine Version, die besonders bei längeren Strings recht flott arbeitet.

Zu einigen anderen Vorschlägen die auf TSysCharSet basieren.

Ich finde, die Vorschläge gehen an der Fragestellung vorbei, denn es war ja nicht gefragt,
Zeichen zu entfernen, die in einem TSysCharSet enthalten sind, sondern Zeichen, die
in einem anderen String enthalten sind.

In dem Zusammenhang :
Was macht ihr, wenn Zeichen zu entfernen sind, die keine Ansizeichen sind z.B. '√'

Delphi-Quellcode:
FUNCTION RemoveChars(const S,Remove:String):String;
type
   TBA=Array[Char] of Boolean;
   TPBA=^TBA;
var P:TPBA; I,J:Integer; C:Char;
begin
   P:=AllocMem(SizeOf(TBA));
   for I:=1 to Length(Remove) do P[Remove[I]]:=True;
   SetLength(Result,Length(S));
   J:=0;
   for I:=1 to Length(S) do begin
      C:=S[I];
      if not P[C] then begin
         Inc(J);
         Result[J]:=C;
      end;
   end;
   SetLength(Result,J);
   FreeMem(P);
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
PeterPanino

Registriert seit: 4. Sep 2004
1.472 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Schnellstes Entfernen von Chars aus einem String?

  Alt 29. Mär 2015, 18:28
Was macht ihr, wenn Zeichen zu entfernen sind, die keine Ansizeichen sind z.B. '√'
set of Char verwenden?

Die Frage ist aber auch: Wieso ist das Nachsehen in einem Char Set schneller als Pos?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.342 Beiträge
 
Delphi 12 Athens
 
#7

AW: Schnellstes Entfernen von Chars aus einem String?

  Alt 29. Mär 2015, 18:31
Es gibt kein Set of Char WideChar.

Unit System.Character oder der Char-Helper.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.629 Beiträge
 
Delphi 12 Athens
 
#8

AW: Schnellstes Entfernen von Chars aus einem String?

  Alt 29. Mär 2015, 18:47
Es gibt kein Set of Char WideChar.
Genau

Weil ein Set compilerbedingt nur aus maximal 256 Elementen bestehen kann.

Die Frage ist aber auch: Wieso ist das Nachsehen in einem Char Set schneller als Pos?
Weil der Test auf ein gesetztes Bit in einem der CPU genehmen Speicherbereich (z.B. DWORD) deutlich schneller geht als die Suche nach einem bestimmten Substring in einem String.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#9

AW: Schnellstes Entfernen von Chars aus einem String?

  Alt 29. Mär 2015, 18:42
Ohne mir nun den Code von Pos anzugucken - Pos kann mehr als nur ein Zeichen vergleichen, es kann ganze Zeichenketten vergleichen. Somit ist der Code vermutlich anders aufgebaut und dadurch langsammer.

Man kann sich das Pas auch sparen und direkt die Chars überprüfen. Dann muss man drauf achten, dass keiner der Strings leer ist. Hier ein Beispiel:
Delphi-Quellcode:
function RemoveCharsFromString(const AStr, CharsToRemove: string): string;
var
  i, k: Integer;
begin
  Result := AStr;
  if Length(CharsToRemove) = 0 then
    Exit;
  for k := 0 to Length(CharsToRemove) do
    for i := Length(Result) downto 0 do
      if Length(Result) > 0 then
        if CharsToRemove[k] = Result[i] then
          Delete(Result, i, 1);
end;
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#10

AW: Schnellstes Entfernen von Chars aus einem String?

  Alt 29. Mär 2015, 23:43
O
Delphi-Quellcode:
function RemoveCharsFromString(const AStr, CharsToRemove: string): string;
var
  i, k: Integer;
begin
  Result := AStr;
  if Length(CharsToRemove) = 0 then
    Exit;
  for k := 0 to Length(CharsToRemove) do
    for i := Length(Result) downto 0 do
      if Length(Result) > 0 then
        if CharsToRemove[k] = Result[i] then
          Delete(Result, i, 1);
end;
Delete ist keine gute Idee, da bei jedem zu löschenden Zeichen alle nachfolgenden Elemente umkopiert werden müssen, was im Average und Worst Case zu quadratischer Laufzeit führt.

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.

Für allerhöchste Performance würde ich eine Hashmap empfehlen (Open Addressing).

Geändert von Namenloser (29. Mär 2015 um 23:52 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:58 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz