2010-03-31 2 views
6

Was würde ich (in Clojure) zu tun:Wie Liste von Wörtern aus Strings entfernen

Zum Beispiel habe ich einen Vektor von Wörtern, die entfernt werden müssen:

(def forbidden-words [":)" "the" "." "," " " ...many more...]) 

.. . und ein Vektor von Strings:

(def strings ["the movie list" "this.is.a.string" "haha :)" ...many more...]) 

So soll jedes verbotenes Wort aus jeder Zeichenfolge entfernt werden, und das Ergebnis wäre in diesem Fall sein: [ „Filmliste“ „thisisastring“ „haha“].

Wie geht das?

+0

wird dieser Link helfen Ihnen: http://github.com/richhickey/clojure-contrib/blob/bacf49256673242bb7ce09b9f5983c27163e5bfc/src/main/clojure/clojure/contrib/string.clj#L162 –

Antwort

7
(def forbidden-words [":)" "the" "." ","]) 
(def strings ["the movie list" "this.is.a.string" "haha :)"]) 
(let [pattern (->> forbidden-words (map #(java.util.regex.Pattern/quote %)) 
       (interpose \|) (apply str))] 
    (map #(.replaceAll % pattern "") strings)) 
+0

Ich mag das besser, weil es nur einen einzigen Durchlauf über die Eingabezeichenfolge durchführt. –

+0

Haben Sie in Bezug auf Ihren Kommentar unten Ihre eigene Antwort mit ["th:) e"] ausprobiert? Es funktioniert nicht richtig, wenn ich es versuche. –

+0

@ALevy Für mich funktioniert er wie erwartet: für ["th:) e" ": das") es gibt aus ("das" ":)") entfernt nur die verbotenen Wörter, die in der Eingabezeichenfolge - und erscheinen nicht verbotene Wörter, die erscheinen, wenn du bereits verbotene Wörter entfernt hast. Meine Lösung ist die einzige, deren Rückgabewerte nicht von der Reihenfolge des Vektors für verbotene Wörter abhängen. – cgrand

1
(use 'clojure.contrib.str-utils) 
(import 'java.util.regex.Pattern) 
(def forbidden-words [":)" "the" "." "," " "]) 
(def strings ["the movie list" "this.is.a.string" "haha :)"]) 
(def regexes (map #(Pattern/compile % Pattern/LITERAL) forbidden-words)) 
(for [s strings] (reduce #(re-gsub %2 "" %1) s regexes)) 
+0

+1, da das funktioniert. Für diejenigen, die dies mit der blutenden Kante testen möchten, beachten Sie, dass 'clojure.contrib.str-utils' in den aktuellen Quellen in' clojure.contrib.string' umbenannt wurde und 're-gsub' zu' 'geworden ist ersetzen-re. Beachten Sie außerdem, dass beim Entfernen eines Worts zwischen zwei anderen Wörtern genau eines der umgebenden Leerzeichen entfernt werden sollte (anstatt wie beim obigen Code keine). * Und * Wörter am Anfang und Ende des Strings sollten korrekt behandelt werden dann wäre etwas mehr involvierte Regex-Magie gefragt. –

+0

Ihr Aufruf von 'Pattern/compile' kann durch' re-pattern' ersetzt werden. –

+0

@Brian: 're-pattern' akzeptiert nicht das' Pattern/LITERAL'-Argument, das hier notwendig ist. –

0

Funktion Zusammensetzung und den von -> Makro diese schön und einfach sein kann:

(for [s strings] 
    (-> s ((apply comp 
      (for [s forbidden-words] #(.replace %1 s "")))))) 

Wenn Sie mehr ‚idiomatischer‘ sein wollen, Sie replace-str von clojure.contrib.string, stattdessen verwenden können von #(.replace %1 s "").

Keine Notwendigkeit, Regexs hier zu verwenden.

+1

Alle Multipass-Antworten sind inhärent gebrochen: (def verbotene Wörter [":)" "the" "." ","]) (für [s [": the)"]] (-> s ((wenden Sie comp an (für [s verbotene Wörter] # (.replace% 1 s "")))))) ;; Dies gibt ("") zurück – cgrand