Hio,
Wollte mal fragen wie ich aus seinem String am besten doppelte Einträge entfernen kann und vor allem effektiv.
Im Moment löse ich es so und es dauert "ewig":
public string getTextStichworte3(string text)
{
//filtert aus dem übergebenen Text doppelte Wörter heraus, so das eine Stichwortsuche daraus entsteht
//und jedes Wort nur noch einmal in dem Text vorkommt
StringBuilder stichworttext = new StringBuilder();
//Herausfiltern von doppelten Einträgen
string temp = "";
while (text.ToString().Length != 0)
{
try
{
temp = text.Substring(0, text.IndexOf(' ')).Trim();
stichworttext.Append(temp + " ");
text = text.Remove(0, text.IndexOf(' '));
text = text.Replace(" " + temp + " ", " ");
text = text.Trim();
}
catch
{
stichworttext.Append(text);
break;
}
}
return stichworttext.ToString();
}
jmd eine gute idee und evtl. noch ein wenig code dazu wäre nice 🙂
aus dem string test = "Hallo ich bins und der hund und die Katze und der Hase"
wird --> "Hallo ich bins der Hund die katze Hase und"
Mein Blog über .NET und MVC / EF | Meine kostenlose Onlinearbeitszeitverwaltung My:Worktime
Hallo,
bist du dir sicher, dass aus deinem String das richtige resultiert? Was passiert mit dem und?
würde es so machen:
Wörter nacheinander abarbeiten (entweder direkt per split beim Leerzeichen trennen oder den Zeiger, den es so ja nicht mehr gibt, immer zum nächsten Leerzeichen weiterlaufen lassen).
Dann in einer Hashtable speichern, ob das Wort schon vorhanden ist, wenns schon vorhanden ist nichts weiter machen, wenn noch nicht, dieses Wort der Hashtable hinzufügen und an einen StringBuilder anhängen (zzgl. Leerzeichen).
Das ganze mit dem StringBuilder kann entfallen, sofern du nur die einzelnen Wörter brauchst und keinen neuen String
Immer noch nicht die Beste Performance, aber deutlich besser als dein Code:
string[] tokens = inputString.Split(' ');
// Hashset wäre besser geeignet, Dictionary geht auch
IDictionary words = new Dictionary<string, string>(tokens.Length);
// Achtung: O(n)
foreach (string token in tokens)
{
if (!words.ContainsKey(token))
words.Add(token, token);
}
// words enthält nun jedes Wort genau einmal
// ein Array lässt sich daraus folgendermaßen erstellen; Achtung: O(n)
string[] wordsArray = new string[words.Count];
words.Values.CopyTo(wordsArray, 0);
// so erstellst du wieder einen string; Annahme, dass ein durschnittliches Wort (einschließlich dem nachfolgenden Leerzeichen) aus sieben Zeichen besteht. Durch schätzen der Länge des fertigen Strings lässt sich die Performance erhöhen. Über die Verwendung eines genaueren Durchschnittswerts sollte nachgedacht werden.
StringBuilder keywordsBuilder = new StringBuilder(inputString.Length - 7 * (tokens.Length - words.Count));
// Achtung O(n)
foreach (string keyword in words.Values)
{
keywordsBuilder.Append(keyword);
keywordsBuilder.Append(" ");
}
// letztes Leerzeichen entfernen
keywordsBuilder.Remove(keywordBuilder.Length - 1, 1);
ok werde ich morgen mal versuchen muss gestehen mit List bzw. Dictionary habe ich noch garkeine erfahrungen gemacht und kenne diese elemente auch nicht wirklich. bzw. list habe ich schonmal in c++ eine erstelle ^^ .
p.s. das "und" hatte ich vergessen ^^ in meinem string.
mfg squadwuschel
Mein Blog über .NET und MVC / EF | Meine kostenlose Onlinearbeitszeitverwaltung My:Worktime
Hallo
die Performance dieser Schleife
foreach (string token in tokens)
{
if (!words.ContainsKey(token))
words.Add(token, token);
}
kann man noch ungefähr verdoppeln:
foreach (string token in tokens)
{
words [token] = token;
}
An der Größenordnung O (n) ändert das allerdings nichts.
herbivore
Deine Stichwortsuche hört sich nach einer einfachen "Volltextsuche" an. Deshalb würde ich auf jeden Fall noch die Stoppwörter entfernen, d.h. die nicht sinntragenden Wörter, die Deinen Stichwortindex nur unnötig aufblähen. Das wären z.B. im Normalfall alle bestimmten / unbestimmten Artikel oder Konjunktionen.
Nur mal als Vorschlag
banzai
2 + 2 = 5 for large values of 2
Mit Regex kann man auch sehr gut doppelte Wörter oder Buchstabenkombis entfernen
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
ja ist richtig sollten am ende alle nicht "sinnvollen" wörter nicht mehr enthalten sein.
was ist regex ?
mfg squadwuschel
Mein Blog über .NET und MVC / EF | Meine kostenlose Onlinearbeitszeitverwaltung My:Worktime
Original von squadwuschel
was ist regex ?
Reguläre Ausdrücke / Regular Expressions.
Bitte solche Stichworte selbst nachschlagen.
Schau dir am besten mal Regex Tutorial an.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
werde ich machen, bisher leider noch nicht dazu gekommen, das auszutesten, noch andere Softwareprobleme ^^
vielen dank erstmal für die vielen antworten
Mein Blog über .NET und MVC / EF | Meine kostenlose Onlinearbeitszeitverwaltung My:Worktime
private string CountWords(string input)
{
char[] delims = new char[]{ ' ', '.', ',',';' };
string[] wordlist = input.Split(delims , StringSplitOptions.RemoveEmptyEntries);
SortedList<string,int> words = new SortedList<string,int>();
//Dictionary<string, int> words = new Dictionary<string, int>(wordlist.Length);
foreach (string item in wordlist)
{
if (!words.ContainsKey(item))
words.Add(item, 1);
else
words[item]++;
}
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string,int> kvp in words)
sb.Append(kvp.Key + ": " + kvp.Value + "\r\n");
//foreach (string item in words.Keys)
// sb.Append(item + ": " + words[item] + "\r\n");
return sb.ToString();
}
maybe this is an option for counting words with few lines of code.
keoma
hio,
also habe ich mal getestet und ist ja krass wie schnell das geht im gegensatz zu meiner ersten lösung wo es teilweise bei großen Dokumenten bis zu 5 min dauern konnte dauert es jetzt maximal noch so 20 sek ^^.
Habe aber mal noch eine kleine Frage zum code.
Den Code verstehe ich ja noch er überprüft ob das angebene Wort in der Collection enthalten ist und wenn nicht wird dieses mit add hinzugefügt.
foreach (string token in tokens)
{
if (!words.ContainsKey(token))
words.Add(token, token);
}
Doch das verstehe ich nicht mehr wirklich, ich würde sagen wenn das wort bereits enthalten ist, wird dieses ersetzt. aber wie wird ein neues eingefügt? oder verstehe ich die Syntax falsch?
foreach (string token in tokens)
{
words [token] = token;
}
bzw. warum entfernt man wörter wie "die", "und", ... nicht einfach mit, sondern nimmt regex ?
Replace("die", "");
...
mfg squadwuschel
Mein Blog über .NET und MVC / EF | Meine kostenlose Onlinearbeitszeitverwaltung My:Worktime
Hallo squadwuschel,
Doch das verstehe ich nicht mehr wirklich, ich würde sagen wenn das wort bereits enthalten ist, wird dieses ersetzt. aber wie wird ein neues eingefügt? oder verstehe ich die Syntax falsch?
bei "meiner" Syntax wird der Wert hinzugefügt, wenn der Key noch nicht vorhanden ist und überschrieben, wenn er schon vorhanden ist. Es ist also nicht nötig, vorher extra zu prüfen, ob der Key schon vorhanden ist.
warum entfernt man wörter wie "die", "und", ... nicht einfach mit, sondern nimmt regex ?
Regex kann man benutzen, wenn man z.B. doppelte Wörter nach dem Muster Muster im Text vorhanden vorhanden sind und man diese entfernen möchte. Für das, was du machen willst, ist Regex unpassend. Wie du schon richtig sagst, würde man einfach alle Stoppworte am Ende aus dem Dictionary rauslöschen.
herbivore
ok danke dir 🙂
achso hast du evtl. einen link wo das dictionary etwas genauer erklärt ist was das genau macht? Vor allem warum es 2 werte hat die beide gleich heissen? Habe zwar schon einige Bücher durchsucht aber nichts genaues über die Funktionsweise von dictionaries gefunden. Nur das es sich um "listen" handelt welche ein paar "spezielle" fähigkeiten bieten wie contains abfrage usw.
mfg squadwuschel
Mein Blog über .NET und MVC / EF | Meine kostenlose Onlinearbeitszeitverwaltung My:Worktime
Hallo squadwuschel,
achso hast du evtl. einen link wo das dictionary etwas genauer erklärt ist was das genau macht? [Artikel] Grundlegendes zu Hashtable/Dictionary
Vor allem warum es 2 werte hat die beide gleich heissen?
Was für zwei Werte, die gleich heißen? Ein Dictionary enthält zu einem Key immer genau einen Wert. Es enthält KeyValuePairs und zwar so, dass jeder Key immer nur genau einmal vorkommt.
herbivore
Im Bsp sind Schlüssel und Wert identisch. Die Verwendung eines Dictionary anstelle einer gewöhnlichen Liste ermöglicht jedoch das auffinden von enthaltenen objekten mit einer operation der Größenordnung O(1).
hio nochmal habe mir mal deinen Artikel durchgelesen und noch eine kleine Frage du hast bei dir so etwas wie:
words["die"] = false
geschrieben, nur das verstehe ich nicht ganz in wie weit das funktioniert, bzw. bei mir schmiert er mir da z.b. ab, wenn ich das noch mit einbaue nachdem ich in words alle wörter gespeichert habe und nun z.b. "die" daraus entferne will. Habe ich da etwas falsch verstanden ?
ich meine so:
words["die"] = "";
geht es ja, wäre das effektiver als Remove ?
mfg squadwuschel
Mein Blog über .NET und MVC / EF | Meine kostenlose Onlinearbeitszeitverwaltung My:Worktime
Hallo squadwuschel,
words["die"] = false
[...] bei mir schmiert er mir da z.b. ab,
das glaube ich kaum. Ich denke, der Compiler meckert da einfach: Da du ein Dictionary<String,String> hast, kannst du nur Strings als Werte verwenden. Ich verwende ein Dictionary<String, bool> und weise entsprechend bools zu.
words["die"] = "";
geht es ja, wäre das effektiver als Remove ?
Ich gehe davon aus, dass sich beides performancemäßig nicht viel nimmt. Ist eher Geschmackssache.
herbivore
ahso
ok danke nochmals für die viele Hilfe.
mfg squadwuschel
Mein Blog über .NET und MVC / EF | Meine kostenlose Onlinearbeitszeitverwaltung My:Worktime