2010-03-31 17 views
6

Quello che vorrei fare (in Clojure):Come rimuovere elenco di parole da stringhe

Ad esempio, ho un vettore di parole che devono essere rimossi:

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

.. . e un vettore di stringhe:

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

Così, ogni parola proibita dovrebbe essere rimosso da ogni stringa, e il risultato, in questo caso, potrebbe essere: [ "lista di film" "thisisastring" "haha"].

Come fare questo?

+0

Sarà questo link vi aiutano a: http://github.com/richhickey/clojure-contrib/blob/bacf49256673242bb7ce09b9f5983c27163e5bfc/src/main/clojure/clojure/contrib/string.clj#L162 –

risposta

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

Mi piace di più perché esegue solo un passaggio sulla stringa di input. –

+0

Per quanto riguarda il tuo commento qui sotto, hai provato la tua risposta con ["th:) e"]? Non funziona correttamente quando lo provo. –

+0

@ALevy Per me, funziona come previsto: per ["th:) e" ": the)"] emette ("il" ":)") rimuovendo solo le parole proibite che appaiono nella stringa di input - e parole non proibite che appaiono quando hai già rimosso le parole proibite di sother. La mia soluzione è l'unica i cui valori di ritorno non dipendono dall'ordinamento del vettore di parole proibite. – 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, dal momento che questo funziona Per coloro che desiderano testare questo con il lato più sanguinante, si noti che 'clojure.contrib.str-utils' è stato rinominato in' clojure.contrib.string' nelle sorgenti correnti e 're-gsub' è diventato' replace-re'. Si noti inoltre che se la rimozione di una parola tra due altre parole dovrebbe comportare la rimozione esatta di uno degli spazi che la circondano (piuttosto che nessuna, come con il codice sopra) * e * le parole all'inizio e alla fine della stringa dovevano essere gestite correttamente quindi, in un certo senso, sarebbe necessaria una maggiore regex per la magia. –

+0

La vostra chiamata a 'Pattern/compile' può essere sostituita con' re-pattern'. –

+0

@Brian: 're-pattern' non accetta l'argomento' Pattern/LITERAL' che è necessario qui. –

0

Utilizzando la composizione e la funzione macro -> questo può essere piacevole e semplice:

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

Se si vuole essere più 'idiomatica', è possibile utilizzare replace-str da clojure.contrib.string, invece di #(.replace %1 s "").

Non è necessario utilizzare regex qui.

+1

Tutte le risposte multipasso sono intrinsecamente interrotte: (def forbidden-words [":)" "the" "." ","]) (per [s [": the)"]] (-> s ((applica comp (per [s parole proibite] # (. Replace% 1 s ""))))))) ;; questo restituisce ("") – cgrand

Problemi correlati