Ordmekanikern
Last updated
Last updated
I denna uppgift ska du skapa en applikation vars uppgift är att analysera en godtycklig text som läses från en textfil och skriva till en annan textfil hur många gånger de olika orden i texten förekommer. Applikationen ska ta textfilernas namn som argument via parametern args
i metoden Main
. Applikationen får endast innehålla statiska klasser och medlemmar där klassen Textanalyzer
måste implementeras minst enligt klassdiagrammet.
Textfilen, Regeringsformen, 1 kap och 2 kap.txt
som finns i uppgiftens repo, ska ge en textfil med innehåll motsvarande Frekvenstabell.txt
som du hittar i lösningen.
TextAnalyzer
Applikationen ska innehålla den statiska klassen TextAnalyzer
vars statiska metoder används för att dela upp en text i ord och bestämma ordens frekvens. Metoderna ska var pure methods innebärande att de inte får av några sidoeffekter ledane till bestående förändringar.
Av klassdiagrammet kan du utläsa att parameterar och returtyper ofta är av interfacetyp, och inte någon konkret typ. Genom att låta metoder returnera en interfacetyp kan du välja vilken klass som helst som ska användas internt inne i metoden, så länge som klassen implementerar nämt interface.
Metoden GetWordFrequncy
ska ha returtypen IDictionary<string, int>
. Ett ”dictionary” består av två värden, en nyckel (key) och ett värde (value). Nyckeln kopplas till värdet, ungefär på samma sätt som ett index i en array kopplas till ett värde. Det finns en konkret klass som heter Dictionary
, en samling som är osorterad, som implementerar interfacet IDictionary
.
Ett Dictionary
-objekt skapar du med IDictionary<string, int> dic = new Dictionay<string, int>();
och redan här kan du använda en variabel av typen IDictionary
för att referera till det skapade objektet. All funktionalitet som du behöver använda definieras av interfacet IDictionary
, och implementeras av klassen Dictionary
. Interfacet IDictionary
definierar bl.a. metoderna ContainsKey()
, Add()
och TryGetValue
, som självklart klassen Dictionary
implementerar. Dessa metoder använder du för att räkna hur många gånger ett ord förekommer och du får då en något låååångsam algoritm.
Något lååångsam algoritm
För varje ord som hittas...
Finns ordet redan i mappen? (ContainsKey
)
...öka heltalet som är kopplat till ordet med 1. (använd operatorn [])
...annars...
...lägg till det nya ordet och initiera heltalet till 1. (Add
, eller operatorn [])
Mindre långsam algoritm
Använd metoden TryGetValue
och känn till att out
-argumentets värde sätts till 0 om ordet inte hittas.
Snabbare algoritm(?)
Parallell bearbetning, Parallel.ForEach
, av textrader vilket kräver användade av en trådsäker samling som t.ex. ConcurrentDictionary
. (Overkill? Yep, but far more interesting!)
Inte mycket kod behöver skrivas om du använder LINQ med GroupBy
och ToDictionary
.
Det står dig fritt att skapa egna statiska klasser för t.ex. applikation, hantering av persistent data, presentation av data, etc.
Efter att ha gjort uppgiften ska du:
Kunna läsa från och skriva till filer.
Kunna instansiera objekt av och hantera objekt instansierade klasser som implementerar interfacet IDictionary
.
Veta hur du använder gränssnittet (interfacet) IDictionary
.
Läs om:
Arrayer
Essential C# 6.0, 71-87. (inte flerdimensionella arrayer).
"for each"-satsen
Essential C# 6.0, 109, 140-142.
Samlingsklasser
Essential C# 6.0, 646 ff.
Interface
Essential C# 6.0, 326-327.
Interfacet IDictionary
Filhantering
Essential C# 6.0, 232-235.
”Online”-dokumentationen om klasserna StreamReader
och StreamWriter
ger en hel del tips och mer exempel rörande filläsning:
(under rubriken Arrays)
Artikeln
StreamReader
,
StreamWriter
,