2010-10-06 12 views
5

Scala oferuje metodę o nazwie stripMargin, która usuwa lewą część ciągu wielowierszowego do określonego separatora (domyślnie: "|"). Oto przykład:Clojure stripMargin

"""|Foo 
    |Bar""".stripMargin 

zwraca ciąg

Foo 
Bar 

Czy istnieje podobna funkcja w Clojure? Jeśli nie, w jaki sposób można go wdrożyć (najbardziej funkcjonalnie)?

Dzięki.

UPDATE: Podany przeze mnie przykład nie jest kompletny. Metoda stripMargin zachowuje również spacje po separatorze:

"""|Foo 
    | Bar""".stripMargin 

zwraca łańcuch

Foo 
    Bar 
+0

Moja odpowiedź wykorzystuje 'ltrim' rozebrać spacje _before_ ogranicznika. –

Odpowiedz

4

Nie ma takiej funkcji wbudowany ale piszesz go łatwo:

user=> (use '[clojure.contrib.string :only (join, split-lines, ltrim)]) //' 
nil 
user=> (->> "|Foo\n |Bar" split-lines (map ltrim) 
    (map #(.replaceFirst % "\\|" "")) (join "\n")) 
"Foo\nBar" 
+0

Zauważ, że Scala 'stripMargin' działa z dowolnym znakiem ogranicznika, ale oczekuje również, że znak będzie pierwszą niepustą znakiem w linii. –

+0

@ abhinv4: zobacz moją aktualizację powyżej. Wydaje się, że obsługuje on wiodące białe znaki za ogranicznikiem: '(- >>" | Foo \ n | Bar "linie podziału (mapa # (. ReplaceFirst%"^\\ s * \\ | "" ")) (dołączenie) \ n "))' ==> '" Foo \ n Bar "' – Ralph

+0

@Ralph: "Wydaje się, że obsługuje on wiodące białe znaki za ogranicznikiem." Czy nie tego właśnie chcesz na pytanie? –

2

Szybkie googling nie zwróciło żadnych istniejących funkcji, ale tutaj jest moja próba na problem. Nie obsługuje niestandardowych ograniczników i nie jest zoptymalizowany pod kątem szybkości.

(use '[clojure.contrib.str-utils :only (re-split re-sub str-join)]) 

(defn strip-margin [s] 
    (let [lines (seq (re-split #"\n" s))] 
    (str-join "\n" 
     (for [line lines] 
     (re-sub #"^\s*\|" "" line))))) 
2

Oto mój kompletne rozwiązanie, zebrane z powyższych odpowiedzi:

(use '[clojure.contrib.string :only (join, split-lines, ltrim)]) 

(defn strip-margin 
    ([s d] (->> s split-lines (map ltrim) (map #(.replaceFirst % d "")) (join "\n"))) 
    ([s] (strip-margin s "\\|"))) 

Oto „prawdziwy "wejście i wyjście próbki:

(println 
    (strip-margin "|<?xml version='1.0' encoding='utf-8'?> 
       |<people> 
       | <person> 
       | <name>Joe Smith</name> 
       | </person> 
       |</people>")) 

==>

<?xml version='1.0' encoding='utf-8'?> 
<people> 
    <person> 
    <name>Joe Smith</name> 
    </person> 
</people> 
nil 

Dziękuję wszystkim współpracownikom.

1

Można również zrobić to za pomocą jednego regexp:

(use '[clojure.contrib.string :only (replace-re)]) 

(def test-string 
"|<?xml version='1.0' encoding='utf-8'?> 
       |<people> 
       | <person> 
       | <name>Joe Smith</name> 
       | </person> 
       |</people>") 


(replace-re #"(^\|)|(.+\|)" "" test-string)) 
+1

Podoba mi się ten jednak, ponieważ Jamie Zawinski słynie z tego, że mówi: "Niektórzy ludzie, gdy stajemy wobec problemu, myślą:" Wiem, użyję wyrażeń regularnych ". Teraz mają dwa problemy. :-) – Ralph

+0

Zgadzam się, pracowałem dużo z regexps w ciągu ostatnich kilku dni i bardzo łatwo jest strzelić sobie w nogę ... Chociaż ta strona pomaga http://gskinner.com/RegExr/ –