Seite 1 von 2

Variablenname als Variable

Verfasst: 22.07.2006 17:39
von Eckhard.S
Problem: Wort aus (langer) Wortliste schnell finden.
Gibt es die Möglichkeit einen Datazugriff variabel zu gestalten? Also je nach Anfangsbuchstabe$ erfolgt der Zugriff auf eine andere DataSection?

-----------------------------------------------

Anfangsbuchstabe$ = "B"

Restore Anfangsbuchstabe$ ; Gibt ERROR! Je nach Buchstabe, soll aber in der richten Liste gelesen werden
Read Wort$
Debug Wort$


DataSection
A:
Data.s "Apfel", "Auto", "Axt"

B:
Data.s "Baum", "Berg", "Birne", "Bohne"

C:
Data.s "Charme", "China"

EndDataSection

-----------------------------------------------

Verfasst: 22.07.2006 17:46
von Kaeru Gaman
löse es nicht per DATA, sondern erstelle die wortliste in einem Array oder einer LinkedList.
dann kannst du elemente sortieren und suchen.

um das mit Data zu lösen, müsstest du ein komplexes Select/Case bauen:

Code: Alles auswählen

Select Asc(Anfangsbuchstabe$)
  Case 65
    Restore A
  Case 66
    Restore B
  Case 67
    Restore C
...
  Case 90
    Restore Z
EndSelect
Restore kann nun mal keine Variablen verarbeiten, da die Labals zur Laufzeit nicht in Klarschrift, sondern nur noch als Pointer vorliegen.

evtl. gibt es auch eine möglichkeit, ein pointerarray zu erstellen...

aber das würde nicht soo viel bringen, da du trotz des immensen aufwands jeden buchstabenblock von vorne durchsuchen müsstest.
da wärest du mit einer fortlaufenden liste und einem guten suchalgorithmus besser bedient...

Verfasst: 22.07.2006 17:58
von Eckhard.S
Die Select - Case - Lösung ist super :allright: ! Danke für den tollen Tipp.

Verfasst: 22.07.2006 18:06
von Kaeru Gaman
hm.. super wäre ne lösung mit nem Array oder ner Liste, aber bitte, ganz wie du willst...

Verfasst: 22.07.2006 18:06
von ts-soft
Vielleicht hilft auch sowas:

Code: Alles auswählen

Structure Dictionary
  key.s
  value.s
EndStructure

Global NewList Dictionary.Dictionary()

Procedure DictPut(key.s, value.s); Add a key with value ( value "" removes the key)
  Protected Found.l
  If CountList(Dictionary())
    ForEach Dictionary()
      If UCase(Dictionary()\key) = UCase(key)
        If value > ""
          Dictionary()\value = value
        Else
          DeleteElement(Dictionary())
        EndIf
        Found = #True
        Break
      EndIf
    Next
  EndIf
  If Not Found
    AddElement(Dictionary())
    Dictionary()\key = key
    Dictionary()\value = value      
  EndIf
EndProcedure

Procedure.s DictGet(key.s); return the value of key or "" if failed
  If CountList(Dictionary())
    ForEach Dictionary()
     If UCase(Dictionary()\key) = UCase(key)
       ProcedureReturn Dictionary()\value
     EndIf    
    Next
  EndIf
  ProcedureReturn ""
EndProcedure

DictPut("Auto", "VW-Käfer")
DictPut("Fahrrad", "Dreirad")
DictPut("Variable", "Wert")
DictPut("Äpfel", "3")

Debug DictGet("Äpfel")
Debug DictGet("Fahrrad")

Verfasst: 22.07.2006 18:21
von Eckhard.S
Noch ein Nachtrag, vielleicht gibt es ja weiter Vorschläge für einen besseren Suchalgorithmus.

Das Ganze soll ein Übersetzungsprogramm für Esperanto werden. Meine Wortliste sieht so aus (ca. 60000 Zeilen):

abako rechenbrett
abandono verzicht
abatiso verhau
abato abt
...
zumuleto summbienchen
zumzumi brummen
zumzumo gesumm

Ich möchte die Liste gerne im Programmcode integrieren und nicht als separate Datei einlesen, daher die "Data" Lösung.

Mit PB habe ich mir ein Programm geschrieben, das mir die Liste als passenden Data-Text ausgibt und auch nach Buchstaben separiert:
A:
Data.s "abako rechenbrett","abandono verzicht","abatiso verhau","abato abt" ...

B:
Data.s "babao rosinenkuchen","babilacxi faseln", ..

mit 4000 Wörtern in einer Data-Zeile geht es nämlich noch. Mit 60000 ging es nicht mehr.

Gibt es noch andere Lösungen, die Übersetzung eines Wortes schnell zu finden?

Verfasst: 22.07.2006 18:24
von Eckhard.S
Danke für die DictPut- Lösung! Die sieht auch gut aus

Verfasst: 22.07.2006 19:03
von Kaeru Gaman
es gibt die sogenannte index-binäre suchmethode.


du könntest genauso ein Array oder eine Liste verwenden, wenn du die Daten in Data-Zeilen übergibst, du kannst sie zu beginn der programmausführung aus den DATA in z.b. ein Array lesen.


die index-binäre suchmethode funktioniert folgendermaßen:

du schaust zuerst in die mitte deiner Datei (also, in Begriff 30000)
dann vergleichst du, ob dein Wort größer oder kleiner ist. (also nachher oder vorher im alphabeth kommt)
wenn vorher, schaust du in die mitte deiner ersten hälfte (also 15000)
wenn nachher, in dir mitte der zweiten hälfte (also 45000)
dann vergleichst du wieder, und halbierst wieder.

so springst du in immer kleineren schritten in deiner datei hin und her,
bis du den richtigen begriff gefunden hast.
damit brauchst du wesentlich weniger zugriffe, als wenn du von vorne oder hinten linear suchen würdest,
und du bist auch auf keine bestimmte struktur angewiesen, um einen guten einsprungpunkt zu finden.

Verfasst: 22.07.2006 19:14
von AND51
Kaeru Gaman hat geschrieben:

Code: Alles auswählen

Select Asc(Anfangsbuchstabe$)
  Case 65
    Restore A
  Case 66
    Restore B
  Case 67
    Restore C
...
  Case 90
    Restore Z
EndSelect
Warum nicht direkt so?

Code: Alles auswählen

Select Anfangsbuchstabe$
  Case "A"
      Restore A
  Case "B"
      Restore B
  Case "C"
      Restore C
EndSelect
??

Verfasst: 22.07.2006 19:39
von hardfalcon
Ich bin mir nicht sicher, aber ich vermute mal, ein Vergleich von Integern ist schneller als ein Vergleich von Strings.