Sagen Sie, ich habe einige Daten wie folgt:
%Vor%Ich möchte es nach "Beulen" suchen, die ein bestimmtes Muster erfüllen.
Stellen Sie sich vor, ich hätte meine eigene angepasste Sprache für die Arbeit mit Zahlen, wobei [[& gt; = 5]] eine beliebige Zahl darstellt & gt; = 5. Ich möchte diesen Fall erfassen:
%Vor%Mit anderen Worten, ich möchte jedes Mal, wenn ich nach vorne schaue, mit der Erfassung beginnen und 3 oder mehr Werte & gt; = 5 in einer Reihe sehen, und die Erfassung jedes Mal stoppen, wenn ich nach vorne schaue und 2+ Werte & lt; 3. Meine Ausgabe sollte also lauten:
%Vor% Beachten Sie, dass das erste 7,8,...
ignoriert wird, weil es nicht lang genug ist und dass die Aufnahme vor dem 0,1,0...
endet.
Ich würde auch gerne ein stream_processor
-Objekt haben, das ich in späteren process
-Aufrufen inkrementell mehr Daten übergeben kann, und gebe erfasste Chunks zurück, wenn sie abgeschlossen sind.
Ich habe einen Code geschrieben, um es zu tun, aber es war hässlich und state-machiney, und ich kann nicht helfen, das Gefühl zu haben, dass ich etwas Offensichtliches vermisse. Irgendwelche Ideen, um das sauber zu machen?
State Machines (die mit einigen Extras angereichert sind, da Regexes mit einer größeren Anzahl von Sprachen als FSMs übereinstimmen können) sind ein typischer Ansatz zur Implementierung von regulären Ausdrucksmaschinen. Warum sollten ähnliche Ansätze bei der Suche nach guten Implementierungen von Ihre gewünschten "Regex-artigen" Konstrukte?
Tatsächlich würde ich in Betracht ziehen, mit dem Code für eine tatsächliche RE-Engine zu beginnen (es gibt eine Python-codierte Version in den PyPy-Quellen, deren Merkurbaum hier ), ändern nur die" primitiven "(Sie brauchen nicht zB \w
oder \s
, aber Sie brauchen <5
, >3
, usw.) und behalten die meisten Syntax und Implementierung für *
, +
und so weiter. Ein solches Projekt wäre übrigens Open-Sourcing wert.
Eine Zustandsmaschine ist hier die geeignete Lösung. Es gibt zwei gebräuchliche Möglichkeiten, eines zu implementieren:
Fest verdrahtet in Form einer Gruppe von gegenseitig rekursiven Funktionen, wobei die laufende Funktion den aktuellen Zustand darstellt. Dies kann sehr effizient sein, erfordert aber Tail Call Elimination, Trampoline oder Goto.
Emuliert in Form einer Datenstruktur, die den aktuellen Status und eine Funktion dieses Status darstellt, und ein neues Eingabedatum, das den Status aktualisiert.
Dieses Zeug ist das Brot und die Butter der funktionalen Programmierung. Hier ist eine elegante Lösung für Ihr Problem, das in dem früheren Stil in F # geschrieben wurde und auf Ihrem eigenen Datensatz läuft:
%Vor%und hier ist die selbe Lösung, die im letzteren Stil geschrieben ist:
%Vor% Beachten Sie, wie die erste Lösung die gesamte Eingabe auf einmal ißt, während die zweite Lösung ein einzelnes Datum auf einmal abbildet und einen neuen Zustand zurückgibt, der bereit ist, ein anderes Datum zu essen. Folglich wird das Letztere nacheinander auf jedes Datum angewendet, wobei ein fold
verwendet wird, und der letzte halb aufgegessene Zustand muss vor der Rückkehr entsprechend verbraucht werden.