Seite 1 von 2
Sortieren wie Excel (Telefonbuch)
Verfasst: 25.09.2006 23:15
von Eckhard.S
Nebenbei: Mein erster Prototyp des Esperanto-Übersetzers ist fertig und kann als Freeware unter
http://www.sauerlandwelle.de heruntergeladen werden.
Zugrunde liegt ein in Excel sortiertes Wörterbuch. Excel sortiert wie ein Telefonbuch:
Ball
Ball treten
Bälle
ballen
Ballpumpe
Ball-Pumpe
Ballzauber
Umlaute werden wie der Stammlaut behandelt und Groß/Kleinschreibung und Bindestriche ignoriert.
Ein If-Abfrage in PB versagt hier
If "Bälle" < "Ballpumpe"
müsste TRUE ergeben. Ebenso müsste "ballen" kleiner als "Ballpumpe" erkannt werden. Hat da jemand eine passende Prozedur, womit ich zwei Strings vergleichen kann?
Verfasst: 25.09.2006 23:52
von Kaeru Gaman
fürs zweite problem: vergleich die upper-case versionen der strings.
(siehe UCase() )
fürs erste:
vor dem checken manuell die umlaute ersetzen.
ggf. auch für ß, falls du das als einfach s einsortiert hast.
der > < vergleich in PB geht streng nach Zeichencode,
und das sind die umlaute nunmal weit über 128.
..auch evtl. akzente solltest du zuvor entfernen...
Gruß nach drüben ins Sauerland.
Verfasst: 26.09.2006 11:21
von Eckhard.S
Danke, Kaeru, für den Lösungsansatz und den Hinweis für Akzentbuchstaben und ß.
Urg - das ganze wird doch etwas komplizierter. Mit einfachem UCase klappt die folgende EXCEL-Sortierung nicht:
anton
an-ton
an-Ton
Anton
An-ton
An-Ton
Antón
änton
än-ton
Änton
Än-ton
In EXCEL steht:
Code: Alles auswählen
Sortieren von alphanumerischem Text sortiert Excel Zeichen um Zeichen von links nach rechts. Enthält eine Zelle beispielsweise den Text "A100", legt Excel diese Zelle hinter eine Zelle mit dem Eintrag "A1" und vor eine Zelle mit dem Eintrag "A11".
Text und Text mit Zahlen werden nach der folgenden Reihenfolge sortiert:
(Leerzeichen) ! # $ % & ( ) * , . / : ";" ? @ [ \ ] ^ _ ` { | } ~ + < = > 0 1 2 3 4 5 6 7 8 9 A Ä B C D E F G H I J K L M N O Ö P Q R S ß T U Ü V W X Y Z.
Apostroph (') und Bindestrich (-) werden mit einer Ausnahme ignoriert: Wenn zwei Textzeichenfolgen sich mit Ausnahme eines Bindestrichs nicht unterscheiden, wird der Text ohne Bindestrich vorangestellt.
Lässt sich das irgendwie verwenden, um ein einfaches Verfahren zu programmieren, wo man die Sortier-Reihenfolge der Zeichen als Liste vorgibt. Dort könnte man dann auch die Akzentbuchstaben einsortieren, so wie es EXCEL macht bzw. wie man es haben will:
a A á Á ä Ä b B
Verfasst: 26.09.2006 11:33
von Kaeru Gaman
aua, also das wird hart.
du kannst ja hierbei nicht einfach alle "a A á Á ä Ä" durch "A" ersetzen,
weil dann ja nix mehr sortiert würde.
das beschneiden bedeutet ja, dass du aus allem lediglich ein Chr(65) machst,
damit es immer vor Chr(66), dem "B" eingeordnet wird.
auch der zwischenstehende bindestrich wird ja als extra-zeichen angesehen,
also würde "AN-TON" natürlich vor "ANATOL" stehen.
(65,78,45,84.. ist kleiner als 65,78,65,84...)
die EXCEL-sortierung bedingt eine komplett andere Zuordnung-Tabelle als in ANSI gegeben.
natürlich wäre so etwas machbar, aber eben doch mit ziemlichen aufwand verbunden.
das wäre in etwas so, als wolle man eine eigene UNICODE entwickeln.
die einfachere lösung wäre:
muss denn deine Tabelle optisch sortiert sein?
wird die sortierte liste wirklich im programm angezeigt/benutzt?
wenn es nur darum geht, dass der suchalgorithmus richtig greifen kann,
dann sortier sie doch einfach nach ANSI und pfeif auf EXCEL....
Verfasst: 26.09.2006 13:57
von Eckhard.S
Kaeru Gaman hat geschrieben:
muss denn deine Tabelle optisch sortiert sein?
Ja, das soll schon so sein, denn ich erstelle in Excel das Wörterbuch und sortiere es dort. Das wäre doof, wenn "ähnlich" hinter "Zirkus" kommt.
Aber ich habe eine Idee mit einer Umsortierung:
Code: Alles auswählen
Dim sortiercode(256)
sortierung$= " !"+Chr(34)+"$%&()*,./:;?@[\]^_`{|}~´+<=>§°0123456789"
sortierung$=sortierung$ + "aAáÁäÄbBcCdDeEéÉèÈêÊfFgGhHiIjJkKlmMnNoOöÖpPqQrRsSßtTuUüÜvVwWxXyYzZ"
For i = 1 To Len(sortierung$)
sortiercode(Asc(Mid(sortierung$,i,1))) = i + 32 ; 32 dazu, damit es druckbare Zeichen werden
Next
Eins$ = "ärgern"
Zwei$ = "blau"
Einskonvertiert$="" ;
Zweikonvertiert$=""
For i = 1 To Len(Eins$)
Einskonvertiert$=Einskonvertiert$ + Chr(sortiercode(Asc(Mid(Eins$,i,1))))
Next
For i = 1 To Len(Zwei$)
Zweikonvertiert$=Zweikonvertiert$ + Chr(sortiercode(Asc(Mid(Zwei$,i,1))))
Next
Debug Einskonvertiert$
Debug Zweikonvertiert$
If Einskonvertiert$ < Zweikonvertiert$ : Debug Eins$ + " ist kleiner als " + Zwei$ : EndIf
If Einskonvertiert$ > Zweikonvertiert$ : Debug Eins$ + " ist größer als " + Zwei$ : EndIf
Die Worte werden in neue umcodiert, die in der vorgegebenen Reihenfolge liegen. Mir geht es ja nur darum, zwei Worte zu vergleichen, ob das eine vor dem anderen kommt oder dahinter.
Verfasst: 26.09.2006 18:30
von Kaeru Gaman
> denn ich erstelle in Excel das Wörterbuch und sortiere es dort.
aber ist das wörterbuch in deinem programm einzusehen,
oder brauchst du es nur für den vergleich?
wenn letzteres, dann sortier es doch vor dem import um,
dann isses doch egal, ob programmintern "ähnlich" hinter "zirkus" kommt.

Verfasst: 26.09.2006 18:37
von Alves
AFAIK benutzt er es im Porgramm, wenn man es benutzt, sieht man klinks unten eine sortierte Tabelle, deutsch-esperanto.
Verfasst: 26.09.2006 20:15
von Eckhard.S
Stimmt! Der User bekommt das Wörterbuch ausgegeben, also benötige ich die Sortierprozedur, die eine Excel-Sortierung simuliert
Verfasst: 26.09.2006 20:52
von Kaeru Gaman
nicht wirklich "sortier", nur "vergleich"...
wird zwar ein bissel knackig,
aber natürlich brauchst du nen funktionierenden vergleich,
um ne suchmethode auf deinem wörterbuch anzuwenden.
(ich empfehle index-binäres suchen... hatten wir letztens erst...)
Verfasst: 26.09.2006 22:33
von Eckhard.S
Ja, das binäre Suchen ist superschnell!
Die Prozedur "Excelvergleich" ist jetzt auch fertig (uff) und damit kann ich schnell vergleichen bei der (binären

) Suche. Die Prozedur lässt sich später mal verwenden um eine Liste zu sortieren.
Code: Alles auswählen
Dim Wort.s(24)
Global Dim sortiercode(256)
Global sortierung$= " !"+Chr(34)+"#$%&()*,./:;?@[\]^_`{|}~´+<=>§°0123456789"
sortierung$=sortierung$ + "aAáÁäÄbBcCdDeEéÉèÈêÊfFgGhHiIjJkKlLmMnNoOöÖpPqQrRsSßtTuUüÜvVwWxXyYzZ'-"
For i = 1 To Len(sortierung$)
sortiercode(Asc(Mid(sortierung$,i,1))) = i + 31 ; 31 dazu, damit es druckbare Zeichen werden
Next
Procedure.s ReplaceStrings(String$, StringsToFind$, StringsToReplace$, Separator$=";")
Protected n.l
For n=1 To CountString(StringsToFind$, Separator$)+1
String$=ReplaceString(String$, StringField(StringsToFind$, n, Separator$), StringField(StringsToReplace$, n, Separator$))
Next
ProcedureReturn String$
EndProcedure
Procedure Excelstringvergleich (string1.s,string2.s) ; wird von Excelvergleich aufgerufen
vergleichsergebnis=0
string1konvertiert$="" ;
string2konvertiert$=""
For scanbuchstabe = 1 To Len(string1.s)
string1konvertiert$=string1konvertiert$ + Chr(sortiercode(Asc(Mid(string1.s,scanbuchstabe,1))))
Next
For scanbuchstabe = 1 To Len(string2.s)
string2konvertiert$=string2konvertiert$ + Chr(sortiercode(Asc(Mid(string2.s,scanbuchstabe,1))))
Next
;Debug string1konvertiert$
;Debug string2konvertiert$
If string1konvertiert$ < string2konvertiert$ : vergleichsergebnis = -1 : EndIf
If string1konvertiert$ > string2konvertiert$ : vergleichsergebnis = 1 : EndIf
ProcedureReturn vergleichsergebnis
EndProcedure
Procedure Excelvergleich (string1.s,string2.s)
string1_ohnebindestrich$ = ReplaceString(string1.s, "-", "")
string2_ohnebindestrich$ = ReplaceString(string2.s, "-", "")
;Debug "1ohnebind: " + string1_ohnebindestrich$
string1_ohnebindestrich_gross_egal$ = LCase(string1_ohnebindestrich$)
string2_ohnebindestrich_gross_egal$ = LCase(string2_ohnebindestrich$)
;Debug "1großegal: " + string1_ohnebindestrich_gross_egal$
string1_ohnebindestrich_gross_egal_umlaute_weg$ = ReplaceStrings(string1_ohnebindestrich_gross_egal$, "á;ä;é;è;ê;ö;ü", "a;a;e;e;e;o;u" )
string2_ohnebindestrich_gross_egal_umlaute_weg$ = ReplaceStrings(string2_ohnebindestrich_gross_egal$, "á;ä;é;è;ê;ö;ü", "a;a;e;e;e;o;u" )
excelvergleichswert = Excelstringvergleich (string1_ohnebindestrich_gross_egal_umlaute_weg$,string2_ohnebindestrich_gross_egal_umlaute_weg$)
;Debug " "
;Debug "Ver1: " + string1_ohnebindestrich_gross_egal_umlaute_weg$
;Debug "Ver2: " + string2_ohnebindestrich_gross_egal_umlaute_weg$
;Debug "Wert: " + Str(excelvergleichswert )
If excelvergleichswert = 0
;Debug "Prüfen Umlaute"
excelvergleichswert = Excelstringvergleich (string1_ohnebindestrich_gross_egal$,string2_ohnebindestrich_gross_egal$)
If excelvergleichswert = 0
;Debug "Prüfen"
excelvergleichswert = Excelstringvergleich (string1_ohnebindestrich$,string2_ohnebindestrich$)
If excelvergleichswert = 0
;Debug "Prüfen"
endergebnis = Excelstringvergleich (string1.s,string2.s)
Else ; fertig
endergebnis = excelvergleichswert
EndIf
Else ; fertig
endergebnis = excelvergleichswert
EndIf
Else
endergebnis = excelvergleichswert
EndIf
ProcedureReturn endergebnis
EndProcedure
;Einlesen
Restore Worte
For zz = 1 To 18
Read Wort.s(zz)
;Debug Wort.s(zz)
Next
;Ausgabe
For zz = 1 To 17
vergleich = Excelvergleich (Wort.s(zz),Wort.s(zz+1))
If vergleich = -1 : vergleich$ = " ist kleiner als " : EndIf
If vergleich = 0 : vergleich$ = " ist gleich " : EndIf
If vergleich = 1 : vergleich$ = " ist größer als " : EndIf
Debug Wort.s(zz) + vergleich$ + Wort.s(zz+1)
Next
End
MessageRequester("Info", "Hallo", #MB_ICONASTERISK)
;MessageRequester("Info", A$, #MB_ICONASTERISK)
DataSection
Worte:
Data.s "haustür","haus-tür","hausTür","haus-Tür","Haustür","Haus-tür","Haus--tür","HausTür","Haus-Tür","HAustür","HAus-Tür","háus-tür","häustür","häusTür","hÄus-tür","HÄus-Tür","Haut", "Häut"
EndDataSection