Avatar billede sbhansen Nybegynder
06. maj 2001 - 16:50 Der 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!



Avatar billede sbhansen Nybegynder
06. maj 2001 - 16:53 #1
Skriv evt. til min mailadresse, hvis du ikke vil have publiceret din mail her på siden, men gerne vil prøve at modtage min kode.

Skriv til
soeren_b_hansen@hotmail.com
Avatar billede sbhansen Nybegynder
06. maj 2001 - 17:02 #2
Det er et VB6 projekt...
Bruger Access 2000 DB\'er
Avatar billede carstenp Nybegynder
06. maj 2001 - 18:11 #3
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.

Hilsen
Carstenp
Avatar billede sbhansen Nybegynder
06. maj 2001 - 20:08 #4
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

/Søren
Avatar billede sbhansen Nybegynder
09. maj 2001 - 15:05 #5
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.
Avatar billede carstenp Nybegynder
09. maj 2001 - 19:22 #6
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.

Avatar billede sbhansen Nybegynder
09. maj 2001 - 20:12 #7
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.
Avatar billede carstenp Nybegynder
14. maj 2001 - 19:16 #8
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.

Carsten
Avatar billede sbhansen Nybegynder
14. maj 2001 - 22:03 #9
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.
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester