2010-03-31 17 views
6

Co chciałbym zrobić (w Clojure):Jak usunąć listę słów z ciągów

Na przykład, mam wektor słów, które muszą zostać usunięte:

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

.. . i wektor ciągów:

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

Więc każdy zabronione słowo powinno być usunięte z każdej struny, a wynik, w tym przypadku, to: [ „lista film” „thisisastring” „haha”].

Jak to zrobić?

+0

Czy ten link pomóc: http://github.com/richhickey/clojure-contrib/blob/bacf49256673242bb7ce09b9f5983c27163e5bfc/src/main/clojure/clojure/contrib/string.clj#L162 –

Odpowiedz

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

Podoba mi się to lepiej, ponieważ wykonuje tylko jedno przejście przez ciąg wejściowy. –

+0

Odnośnie komentarza poniżej, czy wypróbowałeś własną odpowiedź za pomocą ["th:) e"]? Nie działa poprawnie, kiedy go wypróbuję. –

+0

@ALevy Dla mnie działa zgodnie z oczekiwaniami: dla ["th:) e" ": the)"] wyświetla ("the" ":)") usuwając tylko niedozwolone słowa, które pojawiają się w łańcuchu wejściowym - i nie zabronione słowa, które pojawiają się, gdy już usunięto inne zabronione słowa. Moje rozwiązanie jest jedynym, którego wartości zwracane nie zależą od kolejności w wektorze słów zabronionych. – 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, ponieważ to działa. Dla tych, którzy chcieliby przetestować to na krwawiących krawędziach, zauważ, że 'clojure.contrib.str-utils' został przemianowany na' clojure.contrib.string' w bieżących źródłach i 're-gsub' stał się'. replace-re'. Zauważ również, że jeśli usunięcie słowa z dwóch innych słów powinno pociągnąć za sobą usunięcie dokładnie jednej z otaczających go przestrzeni (zamiast żadnego, tak jak w powyższym kodzie) * i * słowa na początku i końcu ciągu były poprawnie obsługiwane Wtedy wezwano by nieco bardziej zaangażowaną magię regex. –

+0

Twoje połączenie z 'Pattern/compile' może być zastąpione' re-pattern'. –

+0

@Brian: 're-pattern' nie przyjmuje argumentu' Pattern/LITERAL', który jest tutaj konieczny. –

0

Korzystanie złożenie funkcji i tym -> makro może to być miła i prosta:

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

Jeśli chcesz być bardziej „idiomatycznych”, można użyć replace-str z clojure.contrib.string, zamiast z #(.replace %1 s "").

Nie trzeba używać tutaj wyrażeń regularnych.

+1

Wszystkie odpowiedzi wielokrotne są z natury uszkodzone: (def zabronione słowa [":)" "" "." ","]) (dla [s [": the)"]] (-> s ((zastosować comp (dla [s zabronione słowa] # (. Replace% 1 s "")))))) ;; to zwraca ("") – cgrand

Powiązane problemy