There's also re-split in str-utils in clojure.contrib;
(use 'clojure.contrib.str-utils)
(re-split #"\s" "The quick brown fox")
=> ("The" "quick" "brown" "fox")
You can then use all the good clojure collection functions;
(def words (re-split #"\s" "The quick brown fox"))
(some #{"brown"} words)
=> "brown"
(some #{"foo"} words)
=> nil
(nth words 2)
=> "brown"
(str-join "," words)
=> "The,quick,brown,fox"
..., etc.
(There's also some good stuff in str-utils2 worth looking at).
The "some" function above needs some explanation;
It takes a predicate, applies it to each element of the collection and
returns the first logical true (not nil) value if found otherwise nil.
The #{"brown"} is a set containing "brown", but sets, like maps are a
function of their elements, e.g;
(#{"a" "b"} "b")
=> "b"
and hence acts as a predicate for testing each element in words in the
some function.
There are also endless things you can do with map and reduce;
(map (fn [w] (.toUpperCase w)) words)
=> ("THE" "QUICK" "BROWN" "FOX")
same as;
(map #(.toUpperCase %) words)
=> ("THE" "QUICK" "BROWN" "FOX")
Say you wanted to encode a "record" of stems from a map of word/stem's;
(let [stems {"the" :th "quick" :qk "brown" :br "fox" :fx}]
(reduce (fn [rec x] (conj rec (stems (.toLowerCase x)))) [] words))
=> [:th :qk :br :fx]
So then given that background and that you're looking for a clojure
approach rather than a specific solution to your "brown" split
example, lets elaborate on a possible approach;
You could "abstract" the requirement to something like;
"Given a collection and a predicate to find an element in that
collection, return two collections - up to the split element and the
remaining elements (including the split element)."
(defn split-coll
"Doc as above."
[coll pred]
(reduce (fn [[l r] x]
(if-not (empty? r) [l (conj r x)]
(if (pred x) [l [x]] [(conj l x) r]))) [[][]] coll))
(split-coll '(:a :b :c) #(= % :b))
=> [:a] [:b :c]]
(split-coll '(:a :b :c) #(= % :x))
=> [[:a :b :c] []]
(split-coll '(:a :b :c) #(= % :a))
=> [[] [:a :b :c]]
and of course;
(split-coll words #(= % "brown"))
=> [["The" "quick"] ["brown" "fox"]]
finally, you could create the specific sentence function;
(defn split-sentence [sentence word] (split-coll (re-split #"\s"
sentence) #{word}))
(split-sentence "The quick brown fox" "brown")
=> [["The" "quick"] ["brown" "fox"]]
and you can also use de-structuring to get exactly what you were
originally looking for;
(let [[l r] (split-sentence "The quick brown fox" "brown")] r)
=> ["brown" "fox"]
To explain the above reduce function ; we start with two empty vectors
in a vector [[][]] and then looping through the collection on each
iteration that vector is passed to the fn as the first arg. We
de-structure that into l and r for the left and right vectors. If r is
not empty we've already found the element, so conj x into the r
vector. Otherwise if x satisfies the pred, conj it to the r vector,
else we haven't got there yet, so conj it to the l vector.
For completeness, I should show a loop/recur alternative as this is a
totally idiomatic clojure technique, but should be used for functional
goals, not just trying to emulate imperative ways.
(defn split-coll
[coll pred]
(loop [c coll [l r] [[][]]]
(if (nil? (seq c)) [l r]
(recur (next c) (let [x (first c)]
(if (nil? c) [l r] (if-not (empty? r) [l (conj r x)] (if
(pred x) [l [x]] [(conj l x) r]))))))))
(split-coll words #(= % "brown"))
=> [["The" "quick"] ["brown" "fox"]]
It is also important to master loop/recur as you can use this more
easily than reduce for complex looping constructs, nested loops,
performant techniques, etc.
I hope that gives you a feel of the kinds of things you can do with
functional idioms and clojure and also a general approach to
functional programming. Takes a while to pickup all these tips but
you'll never look back.
Rgds, Adrian.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---