| Autor |
Beitrag |
Johannes Maier
      
Beiträge: 173
Win XP
D7 Prof
|
Verfasst: Di 07.12.04 19:50
Hi,
ich hab da ein Problem (logisch, sonst würd ich ja nicht posten...): Gibt es eine Möglichkeit, so etwas wie ein Set of String zu deklarieren?
Ich habe bestimmte Befehlswörter in einer Tabelle und möchte diese nun in ein Array schreiben, allerdings möchte ich da nicht schreiben:
Delphi-Quelltext 1:
| if sString = 'DEF' or sString = 'ADD' or ...... etc. |
sondern eher so:
Delphi-Quelltext 1:
| if sString in Befehle then ..... |
Aber man kann ja kein Set of String deklarieren, so wie ich das sehe? Wie bekomme ich das hin, eine Menge dieser Befehle (Strings) zu erstellen um dann eine "in"-Abfrage zu machen?
Danke,
Johannes
_________________ MfG
Johannes ehem. jbmaier
|
|
Pille
      
Beiträge: 105
Windows 7
DelphiXE Prof.
|
Verfasst: Di 07.12.04 20:11
TStringList verwenden, da gibt es die Methode Find.
Pille
|
|
Johannes Maier 
      
Beiträge: 173
Win XP
D7 Prof
|
Verfasst: Di 07.12.04 20:15
TStringList kenne ich, aber kann ich da den in-Operator drauf verwenden? Das mit dem Find ist denke ich immer noch etwas umständlicher als das mit in
Ich brauche das ja nur für die Abfrage, damit die kurz gehalten werden kann.
_________________ MfG
Johannes ehem. jbmaier
|
|
Pille
      
Beiträge: 105
Windows 7
DelphiXE Prof.
|
Verfasst: Di 07.12.04 20:22
Warum kannst du nicht schreiben
Delphi-Quelltext 1:
| if Befehle.Find(sString,position) then |
das entspricht doch in etwa
Delphi-Quelltext 1:
| if sString in Befehle then ..... |
Ich finde das eigentlich nicht aufwändiger.
Pille
|
|
Johannes Maier 
      
Beiträge: 173
Win XP
D7 Prof
|
Verfasst: Di 07.12.04 20:34
Ok danke, dann werd ich das so machen 
_________________ MfG
Johannes ehem. jbmaier
Zuletzt bearbeitet von Johannes Maier am Di 07.12.04 21:18, insgesamt 1-mal bearbeitet
|
|
IngoD7
      
Beiträge: 629
D7
|
Verfasst: Di 07.12.04 20:55
Denke daran, dass Find nur bei sortierten Listen funktioniert. Ansonsten, wie bei DP vorgeschlagen: IndexOf
((Ich mag irgendwie keine Cross-Postings))
|
|
retnyg
      
Beiträge: 2754
SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
|
Verfasst: Mi 02.03.05 16:41
gibts da nicht noch ne elegantere möglichkeit zu prüfen ob ein string in einer menge vorkommt ?
am besten etwas was man als konstante deklarieren kann.
ich hab sowas schon gesehen, weiss nur nicht mehr wie es genau ging
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mi 02.03.05 18:32
Das normale "set of" kann halt vom Compiler komfortabel in Bitoperationen umgewandelt werden. Bei einem "set of byte" muss der Compiler schon mit 256 Bits / 32 Bytes hantieren.
Set of String jedoch wäre von der Art her noch viel komplizierter, es würde einfach drauf hinauslaufen eine Liste mit Strings zu haben und diese zu durchsuchen. Deswegen muss man es selbst programmieren. Für eine schnelle Suche von vielen Strings gibt es sog. Hashfunktionen (such mal im Google oder Forum); die wandeln dir nen String in eine Zahl um (das ist dann natürlich nicht eindeutig möglich).
Tipp: Wenn du die Strings alle in einer sortierten Liste/Array hast, ist die Suche besonders einfach (siehe Binary Search).
|
|
retnyg
      
Beiträge: 2754
SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
|
Verfasst: Do 03.03.05 00:54
na gut; der letzte ansatz den ich gewählt habe war dieser:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| const glyphnames = 'play#pause#stop#back#fwd#mini_miniz#mini_switch#mini_close#';
begin s:=glyphnames; for i := 1 to 8 do begin s2:=copy(s,1,pos('#',s)-1); s :=copy(s,pos('#',s)+1,length(s)); case i of 1..5 : bla(s2); 6..8: blubb(s2); end; end; end; |
wem fällt ne bessere lösung dazu ein ? (voraussetzung: muss als konstante hinterlegt werden können ohne da lange erst zur laufzeit ne stringlist zu erstellen und da die werte reinkopieren, dasselbe gilt für nen array)
bei der variante hier liesse sich mit pos prüfen ob ein string in der liste enthalten ist.
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Do 03.03.05 01:17
@retnyg: Zur Laufzeit reinkopieren? Das wäre ja bei einem Array nicht nötig..
=> Strings sortiert als Array speichern + binäre Suche:
Delphi-Quelltext 1: 2:
| const StrArray : array[1..3] of String = ('alphorn','brieftasche','cervelat'); |
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Do 03.03.05 01:30
@Johannes Maier: Mal ne Frage: Wieviele Befehle gibt es denn? Muss die Liste erweiterbar sein? Kannst du die Befehle mal posten?
Man könnte eventuell etwas recht Simples mit einer trivialen Hashfunktion basteln, wenn es denn nur wenige Befehle sind.
Übrigens: Könntest du nochmals kurz erklären, was du genau tun willst? Willst du einfach überprüfen können ob ein gegebener String eines deiner Befehle entspricht? D.h. ein "function isCommand(S : String) : Boolean" ? Hab ich das richtig verstanden?
Zuletzt bearbeitet von delfiphan am Do 03.03.05 01:38, insgesamt 1-mal bearbeitet
|
|
retnyg
      
Beiträge: 2754
SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
|
Verfasst: Do 03.03.05 01:36
johannesmaiers problem ist schon lange gelöst, ich habe den alten post nur nochmal aufgewärmt da mich das zur zeit beschäftigt. wäre nett wenn du das mit der binären suche oder dem hashwert mal kurz anreissen könntest damit ich ne ahnung bekomme an was du dabei denkst.
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Do 03.03.05 01:44
Lol 13.4.2004. Sorry, hab's nicht gesehn
Eine Hashfunktion ist eine Funktion, die aus einem langen String eine Zahl bastelt. Du kannst damit eine Suche sehr schnell einschränken. Eine etwas blöde Hashfunktion gibt z.B. einfach den ersten Buchstaben des Strings zurück. Eine gute Hashfunktion berücksichtigt alle Zeichen und verhindert möglichst Kollisionen mit anderen Strings.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| var I : Integer; I := HashFunc('Hallo'); Case I of 123: ShowMessage('Das Wort ist "Hallo"'); 412: ShowMessage('Das Wort ist "Welt"'); 921: ShowMessage('Das Wort ist "Delphi"'); 222: ShowMessage('Kollision von zwei Wörtern: Das Wort ist entweder "Windows" oder "Absturz"'); end; |
Eine binäre Suche kannst du in einem sortierten Array durchführen.
Das ist das, was du machst, wenn du ein Wort im Duden nachschaust: Du schlägst den Duden einfach mal in der Hälfte auf, und entscheidest dann, ob sich das gesuchte Wort in der ersten oder zweiten Hälfte des Dudens befindet. Wenn du merkst, dass sich das Wort in der ersten Hälfte befindet, dann machst du dasselbe wieder mit dieser Hälfte, usw. bis du eben am Ziel bist... Wenn du 4 Millarden Wörter hast, hast du nach spätestens 32 Male Blättern das Wort gefunden.
(Hoffentlich war das in etwa verständlich)
|
|
retnyg
      
Beiträge: 2754
SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
|
Verfasst: Do 03.03.05 01:59
hmmm... also das mit der hashfunc erfordert dass ich jeden string einzeln einer zahl zuweise. was das ganze sicher nicht viel einfacher macht (ausser dass ich mit case drauf zugreifen kann)
den theoretischen teil der binären suche habe ich auch gerafft; wo liegt aber jetzt in der praxis der vorteil dran ob ich
if pos(kommando, kommandoliste) > 0 thenoder
if pos(kommando, copy(kommandoliste,1,length(kommandoliste) div 2)) > 0 then mache ?
die 2te variante ist wahrscheinlich noch ein stück langsamer da der string erst zerteilt werden muss.
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Do 03.03.05 02:07
Nee, du musst nicht jedem String eine Zahl zuweisen. MD5 ist z.B. eine Hashfunktion. Oder die CRC checksumme. Eine einfache Summe aller Chars wäre eine Hashfunktion. Alle Chars zusammen ge-xor-t ist eine Hashfunktion. Man kann da vieles mal ausprobieren. Man muss schlussendlich eine wählen, wo es möglichst keine Kollisionen gibt.
Pos durchsucht den String von Anfang bis Schluss und geht einfach linear durch. Wenn die Liste doppelt so lang ist, hat Pos auch doppelt so lange. Der Aufwand ist linear, oder "O(n)". Bei einer binären Suche ist der Aufwand bloss "O(log(n))".
Mit anderen Worten: In der gleichen Zeit, die Pos braucht, um 32 Strings zu durchsuchen, hat die Binäre Suche schon 4 Milliarden Strings durchsucht (Wieso? Um beim Dudenbeispiel zu bleiben: Wenn du den Duden einfach mal in der Hälfte aufschlägst und merkst, dass das gesuchte Wort in der ersten Hälfte ist, dann musst du die zweite Hälfte des Dudens gar nicht berücksichtigen. Du kannst also die Hälfte des Dudens sofort ausschliessen. Du schaust dir die Hälfte aller Wörter gar nicht an. Bei einer linearen Suche gehst du alle Wörter einzeln durch.) Bei einer binären Suche musst du aber ein sortiertes Array haben!
So, bin raus für heute. *weg
Zuletzt bearbeitet von delfiphan am Do 03.03.05 02:12, insgesamt 1-mal bearbeitet
|
|
retnyg
      
Beiträge: 2754
SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
|
Verfasst: Do 03.03.05 02:11
danke für deine tipps, werde drüber noch eingehend meditieren...
gn8
|
|