Buchstabenhäufigkeit in C#

Kann mir jemand einen Tipp geben, wie ich das Vorkommen aller Buchstaben in einem String zählen und ausgeben kann?

Danke!!

Gruß
schmitti81
 
Original von Elderan
Hallo,
wie wäre es mit Zählen?

Schon klar!
Aber wie??

Ich möchte am Ende ein Array (vielleicht ist etwas anderes geschickter) haben in dem dann steht:
a: 1
b: 5
c:3
d:0
...

Weiß einfach schon mal gar nicht wie ich abspeichern soll, wie oft ein Buchstabe schon vorkam.

Danke für die Hilfe.

Gruß
schmitti81
 
Machst dir halt ein Array wie eine Tabelle:

Buchstabe | Häufigkeit
a | 1
b | 2
c | 5
...

und zaehlst dann halt die Häufigkeit hoch. Das wäre die einfachste Lösung, auf die man allerdings auch selber kommen sollte...
 
Bin noch nicht so der Programmier-Gott ;)

Wie kann ich dann in das Array schreiben, wie oft ein Buchstabe vorkam und wie muss ich das Array genau anlegen?

Gruß
schmitti81

EDIT: Wie kann ich wissen an welche Stelle in dem Array 1 dazuaddiert werden muss, z.B. in einer switch-case Anweisung?! Ist aber nicht so schnell, oder?
Geht das auch anders?
 
Original von schmitti81

EDIT: Wie kann ich wissen an welche Stelle in dem Array 1 dazuaddiert werden muss, z.B. in einer switch-case Anweisung?! Ist aber nicht so schnell, oder?
Geht das auch anders?

Hierzu mal die Hilfestellung, dass ein Character, also ein einzelnes Zeichen, durch einen einen Zahlenwert bestimmt wird (Stichwort ASCII). Kannst also damit rechnen wie mit einer Zahl.

Zu den anderen Dingen solltest du dir echt erstmal einige Grundlagen aneignen.
 
Mach das jetzt mit Hashtables. Is ja was ganz geschicktes ;)
Jetzt hab ich nur ein Problem. Er hakt an der Stelle "ht.Keys.CopyTo(astrWords2, 0);"
Fehlermeldung: Das Objekt kann nicht in diesem Arraytyp gespeichert werden.

Is ja auch klar, da steht das ASCII-Zeichen drin und nicht der Buchstabe als string. Aber wie kann ich das ändern?

Hab das davor mit Worten zählen gemacht, das ging so. Deswegen der Fehler. Die Worte wurden in einem string gespeichert.

Code:
            Hashtable ht = new Hashtable();
            string test = "das ist ein test das";
            foreach (char buchs in test)
            {
                if (!ht.Contains(buchs))
                {
                    ht[buchs] = 1;
                }
                else
                {
                    ht[buchs] = ((int)ht[buchs]) + 1;
                }
            }
            String[] astrWords2 = new String[ht.Keys.Count];
            ht.Keys.CopyTo(astrWords2, 0);
            Array.Sort(astrWords2);
            foreach (String buchs in astrWords2)
            {
                Console.WriteLine("{0,-20} = {1,3}", buchs, ht[buchs]);
            }
            Console.Read();

Danke.

schmitti81
 
Hallo,
am besten ne generische Liste nehm:
List<char, int> cnt = new ...;
foreach(char c in meinString)
cnt[c]++;

In cnt steht dann alles was du brauchst
 
Hab es jetzt wie folgt gelöst:
Code:
string strbuchs = Convert.ToString(buchs);
Was ist an einer generischen Liste besser als an einer Hashtable?
Eine Liste kann doch nicht so (List<char, int>) aussehen? Kann die char und int gleichzeitig enhalten? Ich hab da ne Fehlermeldung bekommen.

Gruß
schmitti81
 
Eine Liste ist für so ein Problem nicht besonders geeignet. Viel besser ist die Hashtable oder Dictionary oä. Weil man da ein Element mit fast O(1) gefunden hat. Im Vergleich zur Liste müsste man diese komplett durchsuchen, was natürlich viel viel langsamer wäre. Merken wird man das aber natürlich erst bei langen strings (mit einer Länger über ein paar 1000).
 
Jetzt möchte ich den Hashtable gerne sortieren.
Aber wie kann ich einen Hashtable nach dem Value sortieren? Geht das überhaupt?
Oder brauch ich da eine sorted list?

Gruß
schmitti81
 
ich verstehe nicht, wieso du in diesem fall nicht einfach einen array benutzt. wenn dich groß/kleinschreibung nicht interessiert, dann reichen 26 felder, sonst halt entsprechend mehr.
dann machst du deinen string mit tolower() zu einem mit nur kleinbuchstaben (sofern nötig)
danach gehst du den string zeichen für zeichen durch, holst dir jeweils den int-wert von dem char und (wenn es ein buchstabe ist) dann ziehst du davon einfach 97 ab. in deinem ergebnis-array zählst du den wert an der stelle [int-wert - 97] einfach um eines hoch.
so, dann hättest du einen array der von 0 - 25 läuft (also die buchstaben sortiert repräsentiert und jeweils angibt, wie viele vorkommen von dem bestimmten buchstaben vorgekommen sind. du kannst dann für jeden buchstaben der dich interessiert in konstanter zeit nachsehen, hast das ganze auch gleich sortiert und auch das erstellen des array dauert nur lineare zeit
 
Achso.
Das funktioniert jetzt alles einwandfrei mit Hashtables.
Wie ich das genau mit Arrays machen soll, hab ich noch nicht ganz verstanden.
Ist das schneller oder warum sollte man da keine Hashtables verwenden?

Gruß
schmitti81
 
mit den arrays ists doch ganz simpel:
einfach in zb a[0]-a[25] steht dann die anzahl der buchstaben. hashtabels sind da nicht notwendig, die objekte erzeugen nur unnötigen overhead. würdest du hingeben wörter zählen würdest du die anzahl vorher ja nicht kennen und dann würde die hashtable nützliche dienste leisten.
 
du hast etwa folgende struktur mit dem array wie ich das meinte:

BS Index Anzahl
___________
| a | 0 | 113 |
|---|---|-------|
| b | 1 | 213 |
|---|---|-------|
| c | 2 | 131 |
|---|---|-------|
| d | 3 | 92 |
|---|---|-------|
| e | 4 | 113 |
|---|---|-------|
.
.
.

und in ascii:
.
.
.
______
| a | 97 |
|---|-----|
| b | 98 |
|---|-----|
| c | 99 |
|---|-----|
.
.
.

wenn du nun einfach mit ord(a) zum beispiel den wert von a holst bekommst du 97 (in c# mit (int) 'a') so, da nun die buchstaben halt die indizes 97 - 123 hätten, verschiebt man den index einfach, daher halt sowas in der art:

index = ((int) 'a') - 97;
array[index]++;

das 'a' ist dann natürlich der buchstabe an der aktuellen stelle. und so zählst du halt einfach nur die passende stelle im array hoch.

wenn du nun sagen wir mal alle vorkommen von 'c' in deinem text wissen willst guckst du einfach nur, was in array[2] steht.

das ist halt ne ganz simple aber vollkommen ausreichende und auch schnelle datenstruktur für dieses spezielle problem

hast es jetzt verstanden?
 
Kann ich da auch eine SortedList nehmen, oder ist die auch wieder langsamer.
Komm mit dem Array irgendwie gar nicht zurecht, wie das geht.

Gruß
schmitti81
 
Zurück
Oben