2014-06-17 11 views
6

Ich habe versucht, eine Antwort auf diese Frage zu suchen, konnte aber nichts finden und hoffe, dass es dafür eine einfache Lösung gibt. Ich habe und mit dem folgenden Code in C#,Wie verwende ich RegEx, um die längste Übereinstimmung auszuwählen?

String pattern = ("(hello|hello world)"); 
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase); 
var matches = regex.Matches("hello world"); 

Frage ist, gibt es eine Möglichkeit für die Streichhölzer Methode zuerst die längsten Muster zurück? In diesem Fall möchte ich "Hallo Welt" als mein Match und nicht nur "Hallo" bekommen. Dies ist nur ein Beispiel, aber meine Musterliste besteht aus einer anständigen Anzahl von Wörtern.

+0

Wenn es viele Wörter gibt, die übereinstimmen könnten, warum schlagen Sie ein 'Regex' vor, anstatt, sagen wir, ein' Dictionary'? – ClickRick

Antwort

5

Wenn Sie die Länge der Wörter bereits vorher kennen, dann legen Sie die längste zuerst. Zum Beispiel:

String pattern = ("(hello world|hello)"); 

Die längste wird zuerst abgeglichen. Wenn Sie die Längen vorher nicht kennen, ist das nicht möglich.

Ein alternativer Ansatz wäre, alle Übereinstimmungen in einem Array/Hash/Liste zu speichern und den längsten manuell auszuwählen, indem die eingebauten Funktionen der Sprache verwendet werden.

+1

das funktioniert! das Muster durch die Länge der Wörter zu ordnen, machte den Trick. Vielen Dank! – user3749947

0

Machen Sie zwei verschiedene Regex-Übereinstimmungen. Die erste entspricht Ihrer längeren Option, und wenn dies nicht funktioniert, entspricht die zweite der kürzeren Option.

string input = "hello world"; 

string patternFull = "hello world"; 
Regex regexFull = new Regex(patternFull, RegexOptions.IgnoreCase); 

var matches = regexFull.Matches(input); 

if (matches.Count == 0) 
{ 
    string patternShort = "hello"; 
    Regex regexShort = new Regex(patternShort, RegexOptions.IgnoreCase); 
    matches = regexShort.Matches(input); 
} 

Am Ende matches wird die Ausgabe von „voll“ oder „short“, aber „voll“ wird zuerst überprüft werden und wird Kurzschluss, wenn es wahr ist.

Sie können die Logik in eine Funktion einfügen, wenn Sie sie mehrmals aufrufen möchten. Das ist etwas, was ich mir ausgedacht habe (aber es gibt viele andere Möglichkeiten, wie Sie das tun können).

public bool HasRegexMatchInOrder(string input, params string[] patterns) 
{ 
    foreach (var pattern in patterns) 
    { 
     Regex regex = new Regex(pattern, RegexOptions.IgnoreCase); 

     if (regex.IsMatch(input)) 
     { 
      return true; 
     } 
    } 

    return false; 
} 

string input = "hello world"; 
bool hasAMatch = HasRegexMatchInOrder(input, "hello world", "hello", ...); 
+0

Ich versuche tatsächlich, diese Route zu vermeiden, weil die Musterzeichenfolge tatsächlich viele Wörter/Schlüsselwörter enthält. – user3749947

+0

Sie können jeden Regex-Aufruf immer in eine Funktion umbrechen und mehrmals aufrufen. Das wird eine Menge Copy-Paste-Code reduzieren. – gunr2171

+0

@ user3749947 Wenn Sie nach vielen möglichen Wörtern suchen, dann könnte ein 'Dictionary' besser geeignet sein. – ClickRick

1

Reguläre Ausdrücke (werden versuchen), Muster von links nach rechts zu entsprechen. Wenn Sie sicherstellen möchten, dass Sie zuerst die längste mögliche Übereinstimmung erhalten, müssen Sie die Reihenfolge Ihrer Muster ändern. Die am weitesten links Muster wird zuerst versucht. Wenn eine Übereinstimmung mit diesem Muster gefunden wird, versucht die Engine für reguläre Ausdrücke, den Rest des Musters mit dem Rest der Zeichenfolge abzugleichen. Das nächste Muster wird nur ausprobiert, wenn keine Übereinstimmung gefunden werden kann.

Verwandte Themen