Autor Beitrag
MaxiTB
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 679

Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
BeitragVerfasst: Fr 19.03.04 19:10 
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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
if Value=String1 then
begin
 //Bla1
end else if Value=String2 then
begin
 //Bla2
end else if Value=String3 then
begin
 //Bla3
end else
begin
 //BlaElse
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:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
//--- Global irgendwo ---
gCaseList:=THashedStringList.Create(); // Oder TStringList für alle <D6
gCaseList.Add(String1);
gCaseList.Add(String2);
gCaseList.Add(String3);

//--- Dann bei der Methode ---
case gCaseList.IndexOf(Value) of
 0//BlaElse
 1//BlaElse
 2//BlaElse
 else //BlaElse
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.

_________________
Euer Mäxchen
Wer früher stirbt, ist länger tot.
patrick
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 1481

WIN2k, WIN XP
D6 Personal, D2005 PE
BeitragVerfasst: Fr 19.03.04 19:14 
es geht auch noch so:
ausblenden volle Höhe 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:

  Funktioniert unabhängig von der Klein-/Großscheibung in dem Input-String: 
  Versuchen Sie es z.B. mit "Mother" oder "mOTHER"... 

  Damit kann man seine eigene Makrosprache entwickeln oder bestimmte 
  Teile eines Strings aus einem SQL statement, aus einer wohlgeformten Datei 
  wie im XML-Format...interpretieren. 
}
 


  It works fine and it's not case sensitive: 
  Try to give "Mother" or "mOTHER" in the Input-String... 

  For exemple, you may use this to programm your own macro command system. 
  You can also parse a well formed text file (XML...) 
  Or to interpret a Database Field name as a selector, or whatelse you want. 
}
 


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: www.swissdelphicente...showcode.php?id=1028

ist aber nicht wirklich eine verbesserung

_________________
Patrick
im zweifelsfall immer das richtige tun!!!
MaxiTB Threadstarter
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 679

Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
BeitragVerfasst: 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:

_________________
Euer Mäxchen
Wer früher stirbt, ist länger tot.
matze
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 4613
Erhaltene Danke: 24

XP home, prof
Delphi 2009 Prof,
BeitragVerfasst: Fr 19.03.04 19:22 
haben wir hier in den FAQs oder den Tuts nicht sogar ein workaround zu dem thema ?

_________________
In the beginning was the word.
And the word was content-type: text/plain.
MaxiTB Threadstarter
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 679

Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
BeitragVerfasst: 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: www.delphi-forum.de/viewtopic.php?t=11117

_________________
Euer Mäxchen
Wer früher stirbt, ist länger tot.
MartinPb
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 698



BeitragVerfasst: 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:

ausblenden 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:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
  //--- Global irgendwo ---
  gCaseList:=THashedStringList.Create();
  gCaseList.CommaText:=AnsiUpperCase('String1,String2,String3');

  //--- Dann bei der Methode ---
  case gCaseList.IndexOf(AnsiUpperCase(Value)) of
    0//BlaElse
    1//BlaElse
    2//BlaElse
  else //BlaElse
  end;


Noch einfacher:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
  //--- Global irgendwo ---
  with THashedStringList.Create do
  begin
    CommaText:=AnsiUpperCase('String1,String2,String3');

    //--- Dann bei der Methode ---
    case IndexOf(AnsiUpperCase(Value)) of
      0//BlaElse
      1//BlaElse
      2//BlaElse
    else //BlaElse
    end;
  end;

_________________
Gruß
Martin
obbschtkuche
Gast
Erhaltene Danke: 1



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 390



BeitragVerfasst: 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.