7
votes

Divisez de manière fonctionnelle une chaîne de WhitSpace, groupe par des citations!

Écrire du code fonctionnel idiomatique, à Clojure [1], comment on écrirait une fonction qui scindre une chaîne par blancheur mais garde des phrases citées intactes? Une solution rapide est bien sûr d'utiliser des expressions régulières, mais cela devrait être possible sans eux. À un coup d'œil rapide, il semble assez difficile! J'ai écrit une langue similaire dans des langues impératives, mais j'aimerais voir comment fonctionne une approche fonctionnelle et récursive.

Une commande rapide de ce que notre fonction doit faire: P>

"'lots    of   spacing' there" -> ["lots of spacing", "there"] ;is ok to me


4 commentaires

Dans l'exemple avec des "citations moyennes", j'ai remarqué qu'une seule citation a été complètement laissée complètement. Était-ce intentionnel?


Intentionnel. Mon point de vue de ce problème est que seul le début et la fin d'un mot estime. Je ne sais pas si c'est pratique si ...


Je suppose qu'une approche correcte de ce serait d'abord simplement diviser les cordes des espaces similaires à ceux de Python Split . Cela devrait être presque trivial. Ensuite, vous pourriez probablement regarder la liste pour n'importe quel mot qui commence par une apostrophe et si on se trouve, continuez à chercher un mot qui se termine avec un, puis fusionner les éléments que vous avez déplacés. Type de...


Deniz: Mon approche impérative a utilisé cette méthode. Je dessine une solution récursive mais je ne sais pas si cela va travailler ...


7 Réponses :


1
votes

Utilisez REGEX:

 (defn my-split [string]
  (let [criterion " +(?=([^']*'[^']*')*[^']*$)"]
   (for [s (into [] (.split string criterion))] (.replace s "'" ""))))


3 commentaires

C'est bon. C'est quand même Néater que ma réégalité actuelle :)


Vous ne passez pas le test avec ceci. Vous ["'A B'" "" C D '"] et il devrait être [" A B "," C D "].


En effet. Je viens de le changer pour inclure une solution rapide pour cela.



2
votes

Il y a par exemple fnparse qui vous permet d'écrire un analyseur de manière fonctionnelle.


0 commentaires

5
votes

Cette solution est dans HASKELLL, mais l'idée principale doit également être applicable dans le clojure.
Deux états d'analyseur (intérieur ou extérieur de citations) sont représentés par deux fonctions mutuellement récursives.

splitq = outside [] . (' ':)

add c res = if null res then [[c]] else map (++[c]) res

outside res xs = case xs of
    ' '  : ' '  : ys -> outside res $ ' ' : ys
    ' '  : '\'' : ys -> res ++ inside [] ys
    ' '  : ys        -> res ++ outside [] ys
    c    : ys        -> outside (add c res) ys
    _                -> res

inside res xs = case xs of
    ' '  : ' ' : ys -> inside res $ ' ' : ys
    '\'' : ' ' : ys -> res ++ outside [] (' ' : ys)
    '\'' : []       -> res
    c    : ys       -> inside (add c res) ys
    _               -> res


1 commentaires

C'est beaucoup à ce que j'ai esquissé! Aussi, très cool qu'il évite la division initiale!



3
votes

Voici une version de clojure. Cela souffle probablement de la pile pour de très grandes intrants. Une regex ou un réel analyseur-générateur serait beaucoup plus concis.

user> (doseq [x ["Hello there!"
                 "'A quoted phrase'"
                 "'a' 'b' c d"
                 "'a b' 'c d'"
                 "Mid'dle 'quotes do not concern me'"
                 "'lots    of   spacing' there"]]
        (prn (parse x)))

["Hello" "there!"]
["A quoted phrase"]
["a" "b" "c" "d"]
["a b" "c d"]
["Mid'dle" "quotes do not concern me"]
["lots    of   spacing" "there"]
nil


1 commentaires

Il est assez facile de faire une version de ceci qui ne souffle pas la pile en utilisant trampoline . Je ne parviens pas à éditer cela, donc j'ai copié le vôtre et j'ai légèrement changé et ajouté un exemple qui a soufflé la pile sur ma machine avant le changement.



3
votes

a été capable de modifier Brian's pour utiliser le trampoline pour lui permettre de ne pas manquer d'espace de pile. Fondamentalement faire slurp-word et parse * retourne fonctionner au lieu de les exécuter, puis modifier parse pour utiliser trampoline < Pré> xxx


0 commentaires

7
votes

Voici une version renvoyant un SEQ paresseux de mots / cordes citées: xxx

un test de test: xxx

si célibataire L'entrée ne correspond pas correctement, tout de la citation unique d'ouverture finale est prise pour constituer un "mot": xxx


mise à jour: Une autre version en réponse au commentaire d'Edbond, avec une meilleure manipulation de caractères de devis à l'intérieur des mots: xxx

un test de test: xxx


4 commentaires

Tellement bon ... Je ne suis pas très bon aux séquences paresseuses de Clojure ... si cette séparatrice va avec recur ou donc? Mais l'exécution a l'air très idiomatique et cela sauve l'espacement! Excellent :)


utilisateur => (séparateur "Middle 'citations ne me concerne pas'") ("Middle" "" citations ne "" T "" "est-elle" "moi" ") Je quitterais la citation si elle entourée deux caractères.


@Progo: heureux d'entendre ça. :-) Comme pour recur , non, les SEQ paresseux ne doivent pas être mélangés avec la récursion de la queue. Voir Cette question de sorte pour plus de détails (les réponses peuvent être utiles comme une introduction générale aux SEQ paresseux, et comme pour les SEQS paresseux vs. Récursion de la queue, j'ai essayé de résoudre ce problème dans ma réponse). @edbond: Ouais, j'étais trop paresseux avec ça. La version éditée dans juste maintenant devrait gérer ce genre de cas mieux.


Il y a quelque chose qui se passe ... Le dernier personnage peut être mangé, en "Bonjour là-bas!" et "'Beaucoup d'espacement" là ".



1
votes

Oh mon, les réponses données semblent être la mine debat maintenant que j'ai eu les tests réussir. Quoi qu'il en soit, je le pose ici pour prier quelques commentaires sur l'idiomatisation du code.

J'ai esquissé d'un pseudo haskellish: xxx

ok, mal nommé. Il

  • fonction pl traite les mots pas cité
  • fonction PLI (i comme en intérieur) traite les phrases citées
  • Le paramètre (liste) p est l'information déjà traitée (terminée)
  • Le paramètre (liste) w: ws est des informations à traiter

    J'ai traduit le pseudo de cette façon: xxx

    pas très clojuresque, les détails. De plus, je dépends de Regexp dans la division et en décapant les citations afin que je souhaite mériter des bowvotes en raison de cela.


0 commentaires