2016-04-19 7 views
2

Ich habe die Bibliothek FsVerbalExpressions verwendet, um einige Funktionen zu schreiben. Ich habe eine harte Zeit zu versuchen, ein regEx programmatisch zu erstellen.Programmatisch einen regulären Ausdruck F # mit der FsVerbalExpressions-Bibliothek erstellen

Zum Beispiel, wenn ich einen String "Int. Bus. Mach" habe, kann ich entfernen Perioden und Whitespaces und mit der Anordnung am Ende

let splitString = [|"Int"; "Bus"; "Mach"|] 

Was möchte ich einen regulären Ausdruck von splitString so zu tun ist, zu bauen, dass seine Ergebnis:

let hardCoded = 
    VerbEx() 
    |> startOfLine 
    |> then' "Int" 
    |> anything 
    |> whiteSpace 
    |> then' "Bus" 
    |> anything 
    |> whiteSpace 
    |> then' "Mach" 

hardCoded;; 
val it : VerbEx = 
    ^(Int)(.*)\s(Bus)(.*)\s(Mach) {MatchTimeout = -00:00:00.0010000; 
           Regex = ^(Int)(.*)\s(Bus)(.*)\s(Mach); 
           RegexOptions = None; 
           RightToLeft = false;} 

Mein Problem ist, dass ich weiß nicht, wie dies programmatisch zu bauen, so dass, wenn die ursprüngliche Zeichenfolge "This is a much bigger string" ist, wird die gesamte reguläre Ausdruck Code aufgebaut ist und nicht hart codiert. Ich kann einzelne reguläre Ausdrücke erstellen mit

 let test = 
      splitString 
      |> Array.map (fun thing -> VerbEx() 
             |> then' thing) 
      |> Array.toList 

aber dies ist eine Liste von VerbEx() statt einer einzelnen VerbEx() oben.

Weiß jemand, wie ich eine RegEx mit FsVerbalExpressions programmgesteuert erstellen könnte?

Vielen Dank im Voraus für Ihre Hilfe!

Antwort

5

Denken Sie darüber nach: Sie müssen mit einem Anfangswert beginnen, VerbEx() |> startOfLine, und wenden Sie dann darauf wiederholte Muster an, die die allgemeine Form von anything |> whitespace |> then' word haben. Sie können auch eine Reihe von Werten erzeugen, wobei jeder Wert als previousValue |> anything |> whitespace |> then' word ausgedrückt wird - das heißt, jeder nächste Wert in der Reihe ist ein vorhergehender Wert mit einigen Änderungen. Das letzte Element einer solchen Serie ist Ihre endgültige Antwort.

Eine solche Operation - die eine Reihe von Werten erzeugt, wobei jeder Wert als eine Modifikation der vorherigen ausgedrückt wird - wird traditionell fold genannt. Und sicher genug, hat F # Standard-Bibliothek Funktionen zur Durchführung dieser Operation:

let applyChange previousValue word = 
    previousValue |> anything |> whitespace |> then' word 

let initialValue = VerbEx() |> startOfLine 

let finalAnswer = splitString |> Array.fold applyChange initialValue 

Oder Sie können rollen, dass alle zusammen:

let finalAnswer = 
    splitString 
    |> Array.fold 
     (fun previousValue word -> previousValue |> anything |> whitespace |> then' word) 
     (VerbEx() |> startOfLine) 
+0

Ich bin mäßig neu zu 'F #' und * definitiv * neuer Schreib Falten. Das ist sehr hilfreich. VIELEN DANK! – Steven

+0

Sie können dies sogar ein wenig kürzer machen. Falte umgekehrt, um eta-reduction zu aktivieren: 'VerbEx() |> startOfLine |> Array.foldBack (lustiges Wort -> alles> whiteSpace >> dann 'word) [|" Mach "; "Bus"; "Int" |] ' – kaefer

+0

@kaefer: das würde den Punkt der ansprechbaren Erklärung wirklich zunichte machen und bietet keinen wirklichen Nutzen. –

Verwandte Themen