Sortieren wie Excel (Telefonbuch)

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Eckhard.S
Beiträge: 136
Registriert: 22.07.2006 17:19
Wohnort: Meschede/Sauerland

Sortieren wie Excel (Telefonbuch)

Beitrag von Eckhard.S »

Nebenbei: Mein erster Prototyp des Esperanto-Übersetzers ist fertig und kann als Freeware unter http://www.sauerlandwelle.de heruntergeladen werden. :D

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?
Viele Grüße aus dem Sauerland
Eckhard

PureBasic 4.0 Vollversion, WinXP
Make a better world :D
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Eckhard.S
Beiträge: 136
Registriert: 22.07.2006 17:19
Wohnort: Meschede/Sauerland

Beitrag 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
Viele Grüße aus dem Sauerland
Eckhard

PureBasic 4.0 Vollversion, WinXP
Make a better world :D
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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....
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Eckhard.S
Beiträge: 136
Registriert: 22.07.2006 17:19
Wohnort: Meschede/Sauerland

Beitrag 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.
Viele Grüße aus dem Sauerland
Eckhard

PureBasic 4.0 Vollversion, WinXP
Make a better world :D
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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. ;)
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Alves
Beiträge: 1208
Registriert: 19.04.2006 18:24
Kontaktdaten:

Beitrag von Alves »

AFAIK benutzt er es im Porgramm, wenn man es benutzt, sieht man klinks unten eine sortierte Tabelle, deutsch-esperanto.
Benutzeravatar
Eckhard.S
Beiträge: 136
Registriert: 22.07.2006 17:19
Wohnort: Meschede/Sauerland

Beitrag von Eckhard.S »

Stimmt! Der User bekommt das Wörterbuch ausgegeben, also benötige ich die Sortierprozedur, die eine Excel-Sortierung simuliert
Viele Grüße aus dem Sauerland
Eckhard

PureBasic 4.0 Vollversion, WinXP
Make a better world :D
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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...)
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Eckhard.S
Beiträge: 136
Registriert: 22.07.2006 17:19
Wohnort: Meschede/Sauerland

Beitrag 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


 
Viele Grüße aus dem Sauerland
Eckhard

PureBasic 4.0 Vollversion, WinXP
Make a better world :D
Antworten