Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - case of mit strings
MaxiTB - Fr 19.03.04 19:10
Titel: case of mit strings
Aus aktuellen Anlaß ein kleine Performance-/Erfahrungs-Frage:
Wie wir alle wissen, unterstützt Delphi kein 'case of' mit dem Typen string.
Nun sieht in meinen Programmen der work around bis jetzt so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| if Value=String1 then begin end else if Value=String2 then begin end else if Value=String3 then begin end else begin end; |
Das finde ich aber nicht wirklich hübsch - oder in meiner Landessprache: Des is schiach. Was ja von der Bedeutung aufs selbe rausläuft.
Aber wie kann man jetzt am besten eine Liste von Konstanten flott und fesch checken ?
Ich hab mir foldendes überlegt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| gCaseList:=THashedStringList.Create(); gCaseList.Add(String1); gCaseList.Add(String2); gCaseList.Add(String3);
case gCaseList.IndexOf(Value) of 0: 1: 2: else end; |
Der Aufwand ist zwar ein bisserl höher, aber das ganze ist wesentlich übersichtlicher als die andere Methode - und vielleicht ja auch schneller (vor allem durchs hashing bei vielen Fällen).
Was haltet ihr von diesem Ansatz - oder wißt ihr vielleicht noch einen besseren ?
In meinem Fall muß ein Parser eine Unzahl Commands auswerten (okay, sind nur zwei Dutzend *g*) - da ist mir dieser Gedanke gekommen, besonders, da man diese Liste ja in initialization/finalization unterbringen kann.
patrick - Fr 19.03.04 19:14
es geht auch noch so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
|
uses TypInfo;
type TNumericChoiceParent = (ncp_Mother, ncp_Father, ncp_Child);
procedure TForm1.btChooseClick(Sender: TObject); var S: string; begin S := InputEdit.Text; case TNumericChoiceParent(GetEnumValue(TypeInfo(TNumericChoiceParent), 'ncp_' + S)) of ncp_Mother: ShowMessage('Hello Mom :o)'); ncp_Father: ShowMessage('Hi, Dad -]'); ncp_Child: ShowMessage('Shut up and eat your soup !-('); else ShowMessage('Who do you think that you are?'); end; end; |
quelle:
http://www.swissdelphicenter.ch/de/showcode.php?id=1028
ist aber nicht wirklich eine verbesserung
MaxiTB - Fr 19.03.04 19:20
::patrick
Das ist eine ziemlich fuchsige Idee - muß ich schon sagen *g*.
:arrow: Allerdings - wird die TypeInfo standandmäßig mitgelinkt ?
:arrow: Wie schauts mit der Geschwindigkeit aus - ich will den Parser ja boosten - nicht bremsen ? Schon Erfahrung damit gemacht ?
Ansonsten gefällt mir der Ansatz ziemlich *g* Schade das Delphi keine Macros unterstützt, sonst würd ich gleich eines dafür basteln !
| Zitat: |
| 'Shut up and eat your soup !-(' |
:lol:
matze - Fr 19.03.04 19:22
haben wir hier in den FAQs oder den Tuts nicht sogar ein workaround zu dem thema ?
MaxiTB - Fr 19.03.04 19:26
::matze
Jep - aber wenn du dir das ansiehst, dann merkst du schnell, daß da eine Schleife über die Anzahl der Strings durchlaufen wird.
Ich wollte ja ne Lösung, die unter Umständen schneller ist - aber schon mal mindestens in der selben Klasse spielt.
Deshalb hab ich hier das Thema nochmals angepostet und mir gleich den Link darauf gespart ;-) .
Der Vollständigkeit halber, hier der angesprochene Lösungsvorschlag:
http://www.delphi-forum.de/viewtopic.php?t=11117
MartinPb - Sa 20.03.04 01:25
::MaxiTB
Willst du alle deine Befehle in einer Prozedur auswerten? Ist doch sehr unübersichtlich. Wenn du das auf Prozeduren verteilst, dann sieht das optisch bereits schöner aus:
Delphi-Quelltext
1: 2: 3: 4:
| if Value = String1 then Procedure1 else if Value = String2 then Procedure2 else if Value = String3 then Procedure3 else Procedure4; |
Aber mal zu deinem zweiten Vorschlag. Den kann man auf jeden Fall verfeinern:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| gCaseList:=THashedStringList.Create(); gCaseList.CommaText:=AnsiUpperCase('String1,String2,String3');
case gCaseList.IndexOf(AnsiUpperCase(Value)) of 0: 1: 2: else end; |
Noch einfacher:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| with THashedStringList.Create do begin CommaText:=AnsiUpperCase('String1,String2,String3');
case IndexOf(AnsiUpperCase(Value)) of 0: 1: 2: else end; end; |
Anonymous - Sa 20.03.04 01:48
| MaxiTB hat folgendes geschrieben: |
Jep - aber wenn du dir das ansiehst, dann merkst du schnell, daß da eine Schleife über die Anzahl der Strings durchlaufen wird.
Ich wollte ja ne Lösung, die unter Umständen schneller ist - aber schon mal mindestens in der selben Klasse spielt. |
Und IndexOf errät die Position des Strings?
Das schnellste ist bei strings immer if, da case aus technischer sicht nicht möglich ist (bzw. es würde intern auf if ... else hinauslaufen)
// Edit
Wenn du einen 32-Bit Hash berechnest wirds zwar warscheinlich schneller, aber nicht unbedingt lesbar.
Phantom1 - Sa 20.03.04 09:40
Also wenn's dir um geschwindigkeit geht, ich habe eben mal alle 4 bisherigen lösungvorschläge getestet. Dabei hab ich die Case-anweisung jeweils in einer forschleife 50000 mal durchlaufen, um etwas genauere ergebnisse zu bekommen. gemessen wurde natürlich priority: realtime bzw timecritical.
- "normale IF abfrage" von MaxiTB dauerte etwa 3 millisekunden
- "THashedStringList" von MaxiTB dauerte etwa 24 millisekunden
- "Type" möglichkeit von patrick dauerte etwa 18 millisekunden
- "CaseStr" möglichkeit aus der FAQ von mir (Phantom1) dauerte etwa 10 millisekunden
Das schnellste ist also immernoch die normale IF abfrage, auch wenn's unübersichtlich ist.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!