Teilen Sie eine Zeichenkette funktionell durch Leerzeichen, gruppieren Sie sie in Anführungszeichen!

7

Schreiben von idiomatischem Funktionscode in Clojure [1], wie würde man eine Funktion schreiben, die eine Zeichenkette durch Whitespace teilt, aber zitierte Phrasen intakt hält? Eine schnelle Lösung ist natürlich, reguläre Ausdrücke zu verwenden, aber dies sollte ohne sie möglich sein. Auf den ersten Blick scheint es ziemlich schwer zu sein! Ich habe eine ähnliche in Imperativ-Sprachen geschrieben, aber ich würde gerne sehen, wie ein funktionaler, rekursiver Ansatz funktioniert.

Eine schnelle Überprüfung, was unsere Funktion tun sollte:

%Vor%

Es macht mir nichts aus, wenn sich der Abstand zwischen den Anführungszeichen ändert (so dass man zuerst einfaches Teilen durch Leerzeichen verwenden kann).

%Vor%

[1] Diese Frage könnte im allgemeinen beantwortet werden, aber ich denke, dass ein funktioneller Ansatz in Clojure leicht in Haskell, ML usw. übersetzt werden kann.

    
progo 02.12.2010, 12:20
quelle

7 Antworten

6

Hier ist eine Version, die einen Lazy Seq von Wörtern / zitierten Strings zurückgibt:

%Vor%

Ein Testlauf:

%Vor%

Wenn einzelne Anführungszeichen in der Eingabe nicht korrekt übereinstimmen, wird alles aus dem letzten Anführungszeichen als ein "Wort" genommen:

%Vor%

Update: Eine andere Version als Antwort auf den Kommentar von edbond, mit besserem Umgang mit Zitatzeichen in Wörtern:

%Vor%

Ein Testlauf:

%Vor%     
Michał Marczyk 03.12.2010, 02:38
quelle
5

Diese Lösung ist in Haskell, aber die Hauptidee sollte auch in clojure gelten.
Zwei Parserzustände (innerhalb oder außerhalb von Anführungszeichen) werden durch zwei gegenseitig rekursive Funktionen repräsentiert.

%Vor%     
max taldykin 02.12.2010 14:56
quelle
3

Hier ist eine Clojure-Version. Dies bläst wahrscheinlich den Stack für sehr große Eingaben. Ein Regex oder echter Parser-Generator wäre viel prägnanter.

%Vor%

Ihre Eingaben:

%Vor%     
Brian Carper 02.12.2010 19:51
quelle
3

Es war Brian möglich, Trampoline zu benutzen, damit der Stapelraum nicht ausging. Grundsätzlich make slurp-word und parse* return Funktionen, anstatt sie auszuführen und dann parse ändern, um trampoline

zu verwenden %Vor%     
Jake McCrary 02.12.2010 23:19
quelle
2

Es gibt zum Beispiel fnparse , mit dem Sie den Parser funktional schreiben können.

    
kotarak 02.12.2010 14:24
quelle
1

Benutze Regex:

%Vor%

Das erste Zeichen in Regex ist das Zeichen, mit dem Sie die Zeichenfolge teilen wollen - hier ist es mindestens ein Leerzeichen.

Und wenn Sie das Anführungszeichen ändern möchten, ändern Sie einfach jedes 'zu etwas anderem wie /".

EDIT: Ich habe gerade gesehen, dass du explizit erwähnt hast, dass du Regex nicht benutzen willst. Entschuldigung!

    
Goran Jovic 02.12.2010 13:27
quelle
1

Oh mein Gott, die gegebenen Antworten scheinen meine zu übertrumpfen, jetzt da ich die Tests erfolgreich hatte. Jedenfalls poste ich es hier, um ein paar Kommentare über die Idiomatisierung des Codes zu erbitten.

Ich skizzierte eine haskellische Pseudo:

%Vor%

Okay, schlecht benannt. Dort

  • Funktion pl verarbeitet die Wörter nicht zitiert
  • Funktion pli (i wie in inner) verarbeitet die zitierten Phrasen
  • Der Parameter (list) p ist die bereits verarbeitete (done) Information
  • Der Parameter (list) w:ws ist die zu verarbeitende Information

Ich habe das Pseudo so übersetzt:

%Vor%

Nicht sehr Clojuresque, die Details. Ich bin auch auf Regexp beim Teilen und Entfernen der Anführungszeichen angewiesen, deshalb sollte ich deswegen einige Downvotes verdienen.

    
progo 03.12.2010 08:50
quelle