Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Kein Set of String möglich?
Johannes Maier - Di 07.12.04 19:50
Titel: Kein Set of String möglich?
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
Pille - Di 07.12.04 20:11
TStringList verwenden, da gibt es die Methode Find.
Pille
Johannes Maier - 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.
Pille - 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 - Di 07.12.04 20:34
Ok danke, dann werd ich das so machen :D
IngoD7 - 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 - 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 - 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 - 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 - 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 - 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?
retnyg - 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 - 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 - 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 - 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
retnyg - Do 03.03.05 02:11
danke für deine tipps, werde drüber noch eingehend meditieren...
gn8
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!