2012-04-11 12 views
5

Ich muss überprüfen, ob ein String irgendwelche Schimpfwörter enthält.C# - Schnellste Möglichkeit, einen Satz von Strings in einem anderen String zu finden

hier einige Ratschläge von einer anderen Frage Nach, machte ich eine HashSet, die die Worte:

HashSet<string> swearWords = new HashSet<string>() { "word_one", "word_two", "etc" }; 

Jetzt muss ich sehen, wenn eine der in swearWords enthaltenen Werte in meinen String sind.

Ich habe es umgekehrt, zum Beispiel getan gesehen:

swearWords.Contains(myString) 

Aber das wird false zurück.

Was ist der schnellste Weg zu überprüfen, ob eines der Wörter in der HashSet in myString sind?

NB: Ich denke, ich kann eine foreach-Schleife verwenden, um jedes Wort der Reihe nach zu prüfen und zu brechen, wenn eine Übereinstimmung gefunden wird, ich frage mich nur, ob es einen schnelleren Weg gibt.

+0

Warum sind Sie ein 'HashSet' verwenden? Könnte einfacher sein, 'List ' hier zu verwenden. Dann spalte 'myString' in eine Liste und führe den notwendigen Vergleich durch. – SkonJeet

+1

@SkonJeet: Wenn die Liste der Schimpfwörter groß ist, wird die Suche nach Containment für ein 'HashSet' schneller als eine' List' sein - und ich kann nicht sehen, dass eine 'List' es * einfacher * machen würde. –

+0

Ich benutzte ursprünglich eine Liste und wandelte sie dann in ein HashSet um, während ich las, dass sie schneller sind, um Werte in – surfitscrollit

Antwort

6

könnten Sie einen regulären Ausdruck versuchen, aber ich bin nicht sicher, dass es schneller.

+2

+1 - Swear Wörter sind am besten als reguläre Ausdrücke beschrieben.Ich spreche aus meiner Erfahrung.Allerdings ist es praktisch unmöglich, Benutzer mit einem statischen Algorithmus und einer Wortliste zu schlagen. –

9

Wenn Sie Ihr schwört in einem IEnumerable < platzieren> Umsetzung Behälter:

var containsSwears = swarWords.Any(w => myString.Contains(w)); 

Hinweis: HashSet <> implementiert IEnumerable <>

+2

'HashSet ' implementiert 'IEnumerable '. (Und Sie müssen auf das Scunthorpe Problem achten, wenn Sie diesen Ansatz verwenden: http://en.wikipedia.org/wiki/Scunthorpe_problem) – LukeH

+0

@LukeH: guter Punkt, aber über den Rahmen dieser Diskussion hinaus. Vielleicht besser als Kommentar zu der Frage. +1 – Sprague

+0

lol @ scunthorpe, schöner Name. Wenn jedoch Ihre Logik für das Aufbrechen der Wörter funktioniert, sollten Sie dieses Problem lösen, da Sie ganze Wörter prüfen, keine Strings innerhalb von Wörtern. Ein Problem, das Sie möglicherweise haben, ist die Übereinstimmung der Groß- und Kleinschreibung der Wörter oder Wörter, die leet speak verwenden. –

3

Das Hauptproblem bei solchen Systemen ist definieren, was ein Wort im Kontext der Zeichenfolge Sie überprüfen möchten .

  • Naive Implementierungen wie diejenigen, die input.Contains verwenden, haben einfach nicht das Konzept eines Wortes; Sie werden Schimpfwörter "erkennen", auch wenn das nicht die Absicht war.
  • Das Brechen von Wörtern in Whitespace wird es nicht schneiden (beachten Sie auch Interpunktionszeichen usw.).
  • Das Aufbrechen anderer Zeichen als Whitespace wirft Kulturprobleme auf: Welche Zeichen werden genau als Wortzeichen betrachtet?
  • Unter der Annahme, dass Ihre Stoppwortliste nur das lateinische Alphabet verwendet, wäre eine praktische Wahl, anzunehmen, dass Wörter Sequenzen sind, die nur aus lateinischen Zeichen bestehen.So eine vernünftige Ausgangslösung wäre

    var words = Regex.Split(@"[^\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Pc}\p{Lm}]", myString); 
    

    Die Regex oben ist die Standardklasse \W modifiziert, um nicht Ziffern zu umfassen; Weitere Informationen finden Sie unter http://msdn.microsoft.com/en-us/library/20bw873z.aspx. Für andere Ansätze siehe this question und möglicherweise die in der akzeptierten Antwort angegebene CodeProject-Verknüpfung.

    die Eingabezeichenfolge geteilt haben, können Sie über words laufen und diejenigen ersetzen, die etwas in der Liste übereinstimmen (verwenden swearWords.Contains(word) zu überprüfen) oder einfach zu erkennen, ob es irgendwelche Übereinstimmungen sind überhaupt mit

    var anySwearWords = words.Intersect(swearWords).Any(); 
    
    Verwandte Themen