06. maj 2001 - 16:50Der er
8 kommentarer og 1 løsning
Objektorienteret udfordring...!
Jeg kan vist ikke selv løse det her. Jeg synes faktisk at det er ekstremt svært!
Classes: Address Wordpair MyDatabase
Collections: Dictionary - Col of Wordpairs
Problem: I en destinationsdatabase ( set thisapp.DestinationDB = new Mydatabase) har jeg en tabel med sammensatte adresser (thisapp.destinationdb.primarytable.fieldcombinedaddress), dvs - et felt til fx. Søndre Allé 14, 1.th (et andet felt er postnr) Jeg splitter en sammensat adresse op i Vejnavn, Husnr Appartmentbeskrivelse
Mål: Jeg skal finde samme vejnavn i en Source-database (set thisapp.SourceDB = new MyDatabase), men der er jo som bekendt mange stavefejl i vores måde at stave \"Sdr. Allé\", men i et specifikt postnummer er kun én stavemåde rigtig. Det kunne jo være: Søndre Alle´ Sdr.Alle Sønder Alle Sønder Allé .. osv Men da kun én kombination er rigtig, \"Sdr. Allé\" har jeg en ordbog over alle stavefejl, hvor der er wordpairs over alle mulige stavefejl. Ord1: Alle Ord2: Allé
Ialt 400-500 wordpairs, som loades i en collection
Hvis man finder det ene ord i et wordpair skal man udskifte med det andet ord. Herefter skal man se, om det er genkendt i postnummeret med denne stavemåde. Funktionen skal være rekursiv, således: Sønder Alle\' Word1: Sønder Word2: Sdr. --> ud: word1, ind: word2 -->Sdr. Alle\' Ikke fundet. Ny stavetjek: Word1: Allé Word2: Alle\' --> ud: word2, ind: word1 --> Sdr. Allé FUNDET! Man skal altså kalde sig selv. Samtidig skal der dog maks være fx. 10.000 opslag for én linje, og maks 4 samtidige stavefejl skal tjekkes.
I tjekket skal man ikke i sit rekursive kald \"genkalde\" samme wordpair i omvendt rækkefølge. Det siger jo sig selv at har jeg først erstattet \"Sct.\" med \"Sankt\" så skal den kaldte rekursive funktion i næste gennemløb ikke skifte \"Sankt\" ud med \"Sct.\" for så er jeg jo tilbage i udgangspunktet. Derfor har jeg forsøgt at sætte booleans for de ord i wordpairs, som ER ombyttet. Omvendt må der gerne sættes 2 af samme stavefejl. Det kunne være \".\" til \" \" således at \"S.J. Jensensgade\" bliver til \"S. J Jensensgade\" og senere igen til \"S J Jensensgade\" som findes...
ThisAddress.Roadname skal til sidst sættes til Sdr. Allé - og programmet fortsætter herfra...
Men hvordan får jeg min collection til at arbejde sammen med min Address class. Jeg kan ikke gennemskue det rekursive løb, som skal ende med at påvirke min ThisAddress med den korrekte staveform.
Jeg vil gerne sende det til dig, hvis du er interesseret, og har mod på at prøve at se på min kode. Jeg har lavet koden alt kode, der connecter til forskellige databaser, identificerer forskellige brugbare tabeller og felter, samt splitter adressen op.
Jeg har også forsøgt at lave et gennemløb af collectionen, men jeg kan ikke finde ud af at påvirke min address. Jeg mangler simpelthen rutinen i rekursive funktioners samarbejde med classes!
Jeg tror du er nødt til at kombinere med ét binært træ, hvor der er en alfabetisk eller lign. opdeling af en slags.
I den kan du så godt have nogle rekursive kald, men du ryger hurtigt ud i de samme problemer du har nu. Er du sikker på, at det er nødvendigt at bruge rekursivitet. Det er en forholdsmæssig langsom procedure, så hvis der er mange gennemløb, vil du få en ringe performance.
Det kan være du skal se på problemet med nogle nye \"briller\", og så se om det ikke kan lykkes at lave dine gennemløb uden rekursivitet. Det vil være langt hurtigere.
Nye briller - gerne. Grunden til det rekursive er, at jeg meget hellere vil løse problemet med én række og 20 sekunders rekursivt løb, end springe den over.
Sagens kerne er, at det SKAL udføres, og kan jeg ikke gøre det med mit program, så skal det gøres manuelt. Mit recordset der skal løses startede med 80.000 adresser, og nu har jeg sorteret det ned til 6.000, som min. har 2 stavefejl. De 6.000 vil manuelt tage MANGE dage at gennemløbe. Derfor vil jeg meget gerne lave en procss, som er langsom. Den kan stå og køre i flere dage. Det er stadig bedre end manuelt at udføre det samme.
Det binære træ er en kompliceret affære. Problemet er jo relativt ukendt, når en ny record processeres. Fejlen kan ligge først, midt eller sidst i adressen, eller være en kombination heraf. Jeg har ikke evnen til at opstille sådan noget, desværre :-(
Men jeg vil meget gerne modtage noget konkret - derfor de MANGE point
Jeg ved ikke om mit spørgsmål går imod god skik og brug herinde, ved at tilbyde mange point for en konkret løsning.
Nu har jeg selv brugt 5 timer på dette problem, og løst det med de midler jeg via min sporadiske erfaring har til rådighed. Måske kunne nogle løse det på 10 minutter.
Hvis der er nogle der er interesseret i den kode jeg har stykket sammen, viser jeg den gerne. Min mail står tidligere i denne tråd.
Det kan jo altid være en god ide at få andre til at reviewe sine ideer og arbejde. Så skriv bare løs. Mht. skik og brug, så står det dig fuldstændig frit at sende hvad som helst ud i æteren og belønne det efter behag.
Jeg har spredt problemet lidt rundt til nogle rigtige hajer og venter på respons.
Det lyder kanon, Carsten. Som du kan se på min egen kommentar har jeg løst problemet efter evne. (Når en hammer er det eneste redskab jeg har, ja så får jeg alt til at ligne søm....)
Du kan da sige til dem du omtaler her, at jeg stadig har 400p. til den, der kan komme med den RIGTIGE løsning på et rekursivt løb i en collection (jf. mit eget problem) - eller måske bare den rigtige løsning til at søge mange stavekombinationer igennem for én streng, når stavefejlene ligger som ordpar i en tabel, med hensyntagen til en form for rekursivt kald.
Vi har gennemgået nogle løsningsmodeller, og hvis du lægger din kildekode ind her, kan vi prøve at se lidt nærmere på den og se om der er noget vi kan kommed nogle ændringsforslag der evt. kan hjælpe.
Her er sourcen for den funktion jeg har lagt i min adresse-class. Grunden til at den lægges her er, at jeg ikke kunne finde ud af at placere den, hvor den vel retteligt hører hjemme, nemlig i min dictionary-class. Jeg har kommenteret nogenlunde ned gennem funktionen, så put den evt. i Visual Studio 6.0 for at få lidt overblik. Koden kunne komprimeres en helt del. Fx. kunne den boolske variabel, LookupSuccess, helt undværes, hvis funktionen AdrLookup returnerede en integer istedet for en boolean. Det samme kunne varSpellLoop osv. Men jeg har forsøgt at gøre koden læselig - men det ER altså mit første oo-projekt. --- Private Function SpellLoop(Street As String, ByVal Debth As Integer) As Integer \'1=loop gave me the correct address. 2=Loop is Running...? 0=Not succesfull in this functioncall Dim I As Integer \'Loop-counter Dim J As Integer \'Loop-counter
Dim LookupSuccess As Boolean \' If a address during this loop is found in the code-sourc-DB this boolean is set to TRUE Dim ThisStreet As String Dim NewStreet As String \'Whenever I find a potential spelling-error, the product of the original word and the error is put into this var that calls this same function with the new word (recursive) Dim varSpellLoop As Integer \'This keeps the debth-level of simultaneous spellings equeal or below a stated value in the form Dim use1 As Boolean \'When a spelling is in use, the reverse spelling should never be examined - otherwise it would just change back.... Dim use2 As Boolean Dim SuccesInteger As Integer \'I was not sure if the function should be able to return more than TRUE/FALSE as indication, therefore an integer to hold this value
\'Here I set all booleans to initial values varSpellLoop = 0 \'This holds the returnvalue of the function untill it is given to the function at the end of the function LookupSuccess = AdrLookup(Street) \'Is this address successfull? If so, don\'t go into the loop If LookupSuccess Then varSpellLoop = 1 End If While LookupSuccess = False \'If the address is found, then break the looping For I = 1 To ThisApp.Dictionary.Count \'Looping all the wordpairs in the dictionary ThisStreet = Street \'Setting the street value examined in the loop to the initial value for this branch of the \"tree\" use1 = False use2 = False If mvarSpellCounter >= frmOptions.SpellingTries Then \' max spell-combinations, equaels for instance 150.000 tries per address. GoTo EndOfFunction End If If mvarSpellDebth >= frmOptions.SpellingDebth Then \' Max 4 simultaneously spelling errors GoTo EndOfFunction End If J = 0 \'I now check the wordpair one by one in two seperate if-then structures \' is Word1 of the dictionary allready put into this address on purpose - then skip this check If ThisApp.Dictionary.Item(I).Inuse1 = False Then mvarSpellCounter = mvarSpellCounter + 1 \'Counting the sum of spelling combination tries for this address J = InStr(Street, ThisApp.Dictionary.Item(I).Word1) \'If word1 is in the word then J represents the place it starts If J > 0 Then \'\'debug.print \"Gade før ændring: \" & ThisStreet NewStreet = ThisApp.Dictionary.ChangeSpelling(ThisStreet, J, ThisApp.Dictionary.Item(I).Word1, ThisApp.Dictionary.Item(I).Word2) \'\'debug.print \"Gade efter ændring: \" & NewStreet use2 = True \'If Word1 is in the word, then Word2 is set to TRUE, since I now replace the word1 with word2. ThisApp.Dictionary.Item(I).Inuse2 = use2 \'I have troubles seeing how to set these flags in the best way. ThisApp.Dictionary.Item(I).Inuse1 = True LookupSuccess = AdrLookup(NewStreet) \'The boolean LookupSucces is made to keep the code readable - this line and next line could off course be combined... If LookupSuccess Then varSpellLoop = 1 Else If (Debth + 1) <= frmOptions.SpellingDebth Then \'I only want combinations of 4 simultaneously spellings tested varSpellLoop = SpellLoop(NewStreet, (Debth + 1)) \' Here is the recursive loop End If ThisApp.Dictionary.Item(I).Inuse2 = use2 ThisApp.Dictionary.Item(I).Inuse1 = use1 End If If varSpellLoop = 1 Then GoTo EndOfFunction End If End If End If If (ThisApp.Dictionary.Item(I).Inuse2 = False And SpellLoop = 0) Then mvarSpellCounter = mvarSpellCounter + 1 J = 0 J = InStr(Street, ThisApp.Dictionary.Item(I).Word2) \'debug.print ThisApp.Dictionary.Item(I).Word2 If J > 0 Then \'debug.print \"Gade før ændring: \" & ThisStreet NewStreet = ThisApp.Dictionary.ChangeSpelling(ThisStreet, J, ThisApp.Dictionary.Item(I).Word2, ThisApp.Dictionary.Item(I).Word1) \'debug.print \"Gade efter ændring: \" & NewStreet ThisApp.Dictionary.Item(I).Inuse1 = use1 ThisApp.Dictionary.Item(I).Inuse2 = use2 use1 = True LookupSuccess = AdrLookup(NewStreet) If LookupSuccess Then varSpellLoop = 1 \'Exit Function Else If (Debth + 1) <= frmOptions.SpellingDebth Then varSpellLoop = SpellLoop(NewStreet, (Debth + 1)) End If ThisApp.Dictionary.Item(I).Inuse2 = use2 ThisApp.Dictionary.Item(I).Inuse1 = use1 End If ThisApp.Dictionary.Item(I).Inuse2 = True J = 0 If varSpellLoop = 1 Then GoTo EndOfFunction End If End If End If Next Wend EndOfFunction: SpellLoop = varSpellLoop End Function ---
Den AdrLookup funktion der bliver kaldt viser jeg lige her... --- Private Function AdrLookup(MyStreet As String) As Boolean Dim RsTjek As ADODB.Recordset Dim SQL As String AdrLookup = False SQL = \"SELECT * FROM \" & ThisApp.CodeSourceDB.PrimaryTable & \" WHERE Vejnavn=\'\" & MyStreet & \"\' AND Postnummer=\'\" & mvarZipcode & \"\'\" \'debug.print SQL Set RsTjek = ThisApp.CodeSourceDB.ReturnRecordset(SQL) If Not RsTjek.EOF Then AdrLookup = True mvarstreetname = MyStreet \'Directly influenses the address-object, by letting the streetname equal this street-name, that is the result of the spellingcombinations End If End Function ---
SLUTBEMÆRKNING Jeg mener selv at min kode kunne være langt hurtigere, hvis man arbejdede direkte i Dictionary-collection\'en sådan at et Item(I)-kald ikke skal igennem alle Dot\'ene i addresseringen. Derfor vil jeg gerne splitte det op, og lægge loopet over i dictionary-collectionen.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.