Avatar billede casualty Nybegynder
26. september 2003 - 14:32 Der er 54 kommentarer og
2 løsninger

Hvilken datastruktur bør jeg anvende?

Jeg er igang med at lave en intelligent ordbog (som set på eks. Nokias telefoner). Man skriver et ord og ordbogen kommer selv med et foreslag alt efter hvilke bogstaver man har indtastet...Altså jeg skal have organiseret en pokkers masse danske ord i en form for datastruktur.

Jeg har mine overvejelser om binære søgetræer eller hashmaps, men jeg er ikke helt sikker på hvad der ville give den bedste performance.

Det jeg tænker på, er at programmet skal lede efter et ord på bagrund af 1, 2 eller 3 indtastede bogstaver således at hvis jeg skriver "int" så vil programmet foreslå mig det første resultat den finder i mine data der starter med "int". Altså skal jeg ikke søge i min datastruktur efter hele ordet. Men derimod kun efter det/de ord der starter med mit kriterie.
Hvad ville være mest hensigtsmæssigt at bruge?

Mvh Casualty
Avatar billede arne_v Ekspert
26. september 2003 - 14:36 #1
Du skal have bruge en sorteret liste af en slags.
Avatar billede arne_v Ekspert
26. september 2003 - 14:38 #2
Du kunne bruge java.util.TreeSet, men hvis du ved hvor mange ord du
skal loade inden du loader, så vil et godt gammeldags simpelt array
nok være lige så godt.
Avatar billede jakoba Nybegynder
26. september 2003 - 14:39 #3
Der skal aldrig fjernes noget og kun indsættes ting een enkelt gang. Det din struktur først og fremmest skal bruges til er at slå op. så den del skal prioriteres.

Noget andet der skal prioriteres er plads. en mobilos har ikke for meget.
så jeg ville nok vælge et hashmap. eller måske sågar noget så simpelt som en perfekt heap, implementeret i 2 arrays som du så sifter dine entries ned i. (den er tung at bygge, men når den først er bygget er den hurtig at søge i og fylder endnu mindre end den der hashtabel).

mvh JakobA
Avatar billede arne_v Ekspert
26. september 2003 - 14:40 #4
Men pointen er at det skal være sorteret og relativt nemt at finde
alle der starter med "int".

Og det er eget nemt at finde i et sorteret simpelt array.
Avatar billede arne_v Ekspert
26. september 2003 - 14:41 #5
Jakob>

Det er ikke særligt nemt at finde alle der starter med "int" i en
HashMap.
Avatar billede jakoba Nybegynder
26. september 2003 - 14:46 #6
Helt enig. dit sorterede array er faktisk bedre her
Avatar billede arne_v Ekspert
26. september 2003 - 14:51 #7
Det er faktisk et kendt tradeoff.

                eksakt find          starter med find
hash              O(1)                    O(n)
binær            O(log(n))            O(log(n))
Avatar billede casualty Nybegynder
26. september 2003 - 15:08 #8
Kunne man forestille sig at lave en form for hashmap med arrays som buckets...? Er det der i vil hen?
Avatar billede arne_v Ekspert
26. september 2003 - 15:25 #9
Du mener key=første bogstav og value=simpelt array med alle med det forbogstav ?

Det kunne man godt.
Avatar billede casualty Nybegynder
26. september 2003 - 15:29 #10
Ja det var precis det jeg tænkte...Ville du gøre det på en anden måde?
Avatar billede arne_v Ekspert
26. september 2003 - 15:48 #11
Jeg tror at jeg ville gå efter et simpelt array.

Gevindsten i hastighed ved HashMap + array vil ikke være så stor
og det vil give mere kode.

Men forskellen er ikke stor.

Hvis jeg lige var i hash map humøret, så kunne det også blive den
løsning.
Avatar billede casualty Nybegynder
26. september 2003 - 17:17 #12
Ét enkelt array? Jeg synes at det lyder vildt...Kan du ikke sætte en ca værdi på hvor mange ord du mener at dette array kunne indeholde og stadig være nogenlunde hurtigt?
Avatar billede arne_v Ekspert
26. september 2003 - 17:20 #13
Husk du laver binær søgning !

1 ord = 1 sammenligning
2 ord = 2 sammenligninger
4 ord = 3 sammenligninger
8 ord = 4 sammenligninger
16 ord = 5 sammenligninger
...
1024 ord = 11 sammenligninger
...
4 milliarder ord = 33 sammenligninger
Avatar billede arne_v Ekspert
26. september 2003 - 17:25 #14
En ordbog vil vel typisk indeholde 10000-100000 ord - det giver
15-18 sammenligninger.

Det er ikke noget problem.
Avatar billede casualty Nybegynder
26. september 2003 - 22:25 #15
Jeg har netop færdiggjort det...Jeg lavede hashmap med første bogstav som key og en arraylist som værdi.. Pænt?? Måske ikke, men den søger på max 1/100 af et sekund med 60.000 ord i sin map....Det er godt nok til mig...BTW er der nogen der har et link til en fil med alle danske ord??

Arne>> Smid et svar
Avatar billede arne_v Ekspert
26. september 2003 - 22:41 #16
Jeg kan ikke vurdere om det er hurtigt eller langsomt i frohold til
problem-stilline, så måtte jeg teste forskellige løsninger og
sammenligne.

Men det betyder heller ikke så meget. Det relevante er at 1/100 sekund er
mere end tilstrækkeligt til at løse opgaven til brugerens tilfredshed.
Avatar billede soreno Praktikant
26. september 2003 - 22:43 #17
>>BTW er der nogen der har et link til en fil med alle danske ord??
http://da.speling.org/filer/dsdo-1.4.26.zip
Avatar billede soreno Praktikant
26. september 2003 - 22:44 #18
Noget kunne tyde på denne var nyere:
http://da.speling.org/filer/dsdo-1.4.27.zip

:=)
Avatar billede casualty Nybegynder
26. september 2003 - 23:13 #19
Tak til alle Arne, soreno og jakoba ... Så mangler jeg bare lige at høre om en sidste ting... Filen jeg henter med alle de danske ord er en flad fil med alle ord adskildt af små firkanter...Representerer disse firkanter et linieskift når teksten formateres?
Hvordan fanges disse af java´en? indtil videre har jeg brugt en filereader der læser en linie ad gangen og fyrer det hele ind i en Stringtokenizer for at kunne skille ordene ad...Hvordan får jeg fanget og individualliseret de nye ord?

Soreno>> læg lige et svar
Avatar billede casualty Nybegynder
26. september 2003 - 23:14 #20
Også Jacoba..Læg et svar...

Jeg har forhøjet pointantallet så der er nok til alle
Avatar billede arne_v Ekspert
26. september 2003 - 23:15 #21
Hvis jeg skulle gætte:

så kører du Windows, bruger en editor som kun genkender <CR><LF> som
linieskift og filen bruger <LF>.

Løsning hvis rigtigt gæt:

hiv filen ind i en edtor som genkender <LF> og få den til at gemme
som <CR><LF>.
Avatar billede arne_v Ekspert
26. september 2003 - 23:15 #22
NB: Laver du binær eller sekventiel søgning i arrayet du henter ud ?
Avatar billede casualty Nybegynder
26. september 2003 - 23:21 #23
Sekventiel... for(i=0;i<al.size;i++)
Avatar billede casualty Nybegynder
26. september 2003 - 23:21 #24
Binær ville nok hjælpe en del når nu jeg kommer op over 300.000 ord
Avatar billede casualty Nybegynder
26. september 2003 - 23:22 #25
Kan ultraedit klare den tror du...Jeg prøver...
Avatar billede arne_v Ekspert
26. september 2003 - 23:24 #26
Ja.

Lad os sige at det mest hyppige bogstav har 15000 ord.

Linær worst case er 15000 sammelgninger.

Binær worst case er 15 sammenligninger.

Det kan muligvis mærkes.
Avatar billede arne_v Ekspert
26. september 2003 - 23:24 #27
Jeg vil tror at UE kan læse begge og gemme i eksplicit format.
Avatar billede casualty Nybegynder
26. september 2003 - 23:41 #28
Det kan jeg slet ikke overskue i UE...Har du et tip til en editor der kan køre i windows og tager 2 sek. at hente?
Avatar billede arne_v Ekspert
26. september 2003 - 23:50 #29
Ikke 2 sekunder.

JEdit fra www.jedit.org bruger jeg selv en hel del (jeg kan nemlig bruge
den på Windows, Linux, VMS etc.)

I den er det:
  utilities
  buffer options
  line separator
Avatar billede soreno Praktikant
27. september 2003 - 07:40 #30
Svar
Avatar billede casualty Nybegynder
27. september 2003 - 17:24 #31
Binær søgning er det med at vælge midten og derefter se om objektet er størrer eller mindre end det man leder efter, og derefter dele op igen osv...?
Og hvorfor hedder det egentlig binær søgning?
Avatar billede arne_v Ekspert
27. september 2003 - 17:25 #32
Ja.

bi=2 og man deler op i 2 dele.
Avatar billede casualty Nybegynder
27. september 2003 - 17:28 #33
Ok selvfølgelig :)
Avatar billede casualty Nybegynder
27. september 2003 - 19:56 #34
Der er stadig lidt af et problem...Jeg skal jo ikke søge efter ét ord i min hashmap. Den skal returnere en liste af ord der starter med de indtastede bogstaver.. Kan man stadig anvende binær søgning til det??
på nuværende tidspunkt returnerer mit hashmap en arraylist af Strings som starter med de bogstaver man spørger efter...
Avatar billede casualty Nybegynder
27. september 2003 - 20:03 #35
Måske skulle jeg lave et hasmap med et bogstav som nøgle og et nyt hashmap som værdi hvori dette ordets 2.bogstav var nøgle en arraylist var værdien?
Avatar billede arne_v Ekspert
27. september 2003 - 20:07 #36
Det troede jeg at du havde lavet.

HashMap til at finde array med alle ord der starter med bogstav og så
søgning i det array efter ord.

Og at du kun skulle skifte fra sekventiel søgning til binær søgning indenfor
det array.

Og selvfølgelig kan man anvende binær søgning i det array.

Eneste krav er at data er sorteret.
Avatar billede arne_v Ekspert
27. september 2003 - 20:12 #37
Hvordan vil du håndtere ord på 1 bogstav ?
Avatar billede casualty Nybegynder
27. september 2003 - 20:16 #38
Det havde jeg også lavet...Jeg har et hashmap med forbogstavet som nøgle og en arraylist med stringobjekter som værdi..Det virker fint der er 380000 ord i. Men jeg vil nu ændre det fra sekventiel til binær søgning. Jeg har konstrueret det således at man tilgår mit hashmap via en metode der får en String med som parameter. Denne metode returnerer en arraylist med de stringobjekter fra hashmappen der starter med den string man sendte med som parameter.

Alt dette foregår sekventielt, det vil sige via. en forlykke der kører igennem en af hashmappens arraylister (alt efter forbogstav) og hiver matchende resultater(sammenlignet på forbogstaver) ind i en ny arraylist som den returnerer...Det er dette jeg gerne ville have gjort binært...
Avatar billede casualty Nybegynder
27. september 2003 - 20:17 #39
Jeg har valgt ikke at ville håndtere ord på 1 bogstav.
Avatar billede casualty Nybegynder
27. september 2003 - 20:18 #40
Man søger aldrig på 1 ord...Man søger på ord der starter med xxx...
Avatar billede arne_v Ekspert
27. september 2003 - 20:30 #41
Det er vel bare at implementere din binære søgning i det array du står med !?
Avatar billede arne_v Ekspert
27. september 2003 - 20:33 #42
Eller vil du gerne se et eksempel på binær søgning ?
Avatar billede casualty Nybegynder
27. september 2003 - 20:46 #43
Det kan godt være at jeg ikke fatter det helt, men er binær søgning ikke kun ideélt hvis jeg vil søge på et aksakt ord, det jeg søger efter er jo alle ord der starter med xxx, altså skulle den binære søgning jo resultere mere end et match...Bliver den så ikke sekventiel alligevel??
jeg søger efter 'and'...Den binære søgning halverer indtil den står med 'andalusien'...Hvad herefter??? Skal den søge igen for at finde 'andedam', 'anders' og 'andres'??

Det er meget muligt at jeg ikke kan se skoven for bare træer.. :)

(for points selvfølgelig)
Avatar billede casualty Nybegynder
27. september 2003 - 20:50 #44
Der manglede lige noget i tråden:

Du må da meget gerne komme med et eksempel på en binær søgning der returnerer en række resultater baseret på forbogstaver fra et array (for points selvfølgelig)
Avatar billede arne_v Ekspert
27. september 2003 - 20:54 #45
Jeg prøver lige at lave et simpelt eksempel (simpelt = færre end 380000 ord).
Avatar billede casualty Nybegynder
27. september 2003 - 20:55 #46
Hehe...Fedt tak :)
Avatar billede bearhugx Nybegynder
27. september 2003 - 21:22 #47
cas  >> er også igang med at lave et eksempel (også for min egen fornøjelse) ...  Men jeg tænkte på... skal det være en "nummer-styret" opslagsmetode, dvs. tasten "2" dækker over A, B og C ; "3" dækker over D E og F lige som når man skriver "hurtige" sms'er på nokia-telefoner...


mvh
/23274849 (bearhugx)
Avatar billede casualty Nybegynder
27. september 2003 - 21:25 #48
bearhugx >> Nej den kører direkte på tasterne på tastaturet :)
Avatar billede bearhugx Nybegynder
27. september 2003 - 21:25 #49
ok..
Avatar billede arne_v Ekspert
27. september 2003 - 22:16 #50
import java.util.Arrays;
import java.util.HashMap;

public class NameLookup {
    private HashMap data = null;
    public NameLookup() {
        data = new HashMap();
        String[] as = { "Arne", "Anders", "Asger", "Allan" };
        String[] bs = { "Børge", "Benny", "Brian", "Billy", "Bastian", "Bo", "Benjamin", "Be" };
        String[] cs = { };
        Arrays.sort(as);
        Arrays.sort(bs);
        Arrays.sort(cs);
        data.put("A", as);
        data.put("B", bs);
        data.put("C", cs);
    }
    public String matches(String s) {
        if(s.length() < 1) {
            return "";
        }
        String[] a = (String[])data.get(s.substring(0,1));
        if(a == null) {
            return "";
        }
        if(a.length <= 0) {
            return "";
        }
        StringBuffer sb = new StringBuffer("");
        int l = 0;
        int lmax = a.length - 1;
        while(lmax > l) {
            int med = (l + lmax) / 2;
            int cmp = s.compareTo(a[med]);
            if(cmp <= 0) {
                lmax = med;
            } else if(cmp > 0) {
                l = med + 1;
            }
        }
        if(a[l].indexOf(s) != 0) {
            return "";
        }
        int r = l;
        while((r < a.length) && (a[r].indexOf(s) == 0)) {
            r++;
        }
        for(int i = l; i < r; i++) {
            if(i > l) {
                sb.append(" ");
            }
            sb.append(a[i]);
        }
        return sb.toString();
    }
    private static NameLookup wl;
    public static void main(String[] args) {
        wl = new NameLookup();
        test("As");
        test("Ax");
        test("Be");
        test("Ba");
        test("Bø");
        test("B");
        test("Ca");
        test("De");
    }
    public static void test(String s) {
        System.out.println(s + " : " + wl.matches(s));
    }
}
Avatar billede arne_v Ekspert
27. september 2003 - 22:16 #51
Koden blev ikke så pæn.

Men output ser korrekt ud:

As : Asger
Ax :
Be : Be Benjamin Benny
Ba : Bastian
Bø : Børge
B : Bastian Be Benjamin Benny Billy Bo Brian Børge
Ca :
De :
Avatar billede arne_v Ekspert
27. september 2003 - 22:17 #52
Man kunne naturligvis også finde r med en binær søgning, men det er næppe
umagen værd.
Avatar billede casualty Nybegynder
30. september 2003 - 11:48 #53
Ok...Jeg ser ideen, tak for koden...Den virker men kommer engangimellem med et ukorrekt output..Jeg kigger selv på det og finder fejlen :)

Hvor mange points synes du at dit 2. svar er værd?? Så opretter jeg et nyt spørgsmål.... :)
Avatar billede arne_v Ekspert
30. september 2003 - 12:01 #54
Ukorrekt output ? Det lyder ikke godt !

Kan du sige i hvilke tilfælde det går galt ?
Avatar billede arne_v Ekspert
30. september 2003 - 12:01 #55
Point ?

Det vil jeg helt overlade til dig !
Avatar billede casualty Nybegynder
30. september 2003 - 21:39 #56
Hej...Jeg har lavet et nyt spørgsmål med points i til dig(http://www.eksperten.dk/spm/408016). Angående fejlen så skal jeg nok vende tilbage...jeg ved ikke endnu hvornår men tiden er lidt knap...Tak for Hjælpen.

Mvh Casualty
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