When I saw the part about traversing an arbitrarily nested collection,
I immediately thought of clojure.walk (http://clojure.github.com/
clojure/clojure.walk-api.html).  I ended up with this:

(use 'clojure.walk)

(defn all-vals [k coll]
  (let [vals (atom [])
        find-val (fn [form]
                   (if-let [val (k form)] (swap! vals conj val))
                   form)]
    (prewalk find-val coll)
    @vals))

user=> (all-vals :distance {:goat "al" :distance 35})
[35]

user=> (all-vals :distance [{:goat "al" :distance 35}
                     {:goat "paula" :distance 25}])
[35 25]

user=> (all-vals :distance [{:goat "al" :distance 35}
                     {:goat "paula" :distance 25 :other {:distance 99}}])
[35 25 99]

I wanted to use walk in a purely functional manner (instead of the
current approach of iteratively updating 'vals').  However, I was
unable to do this, given that the function passed in to prewalk needs
to preserve the structure of the nested collections.  Hopefully
someone can find a way to use walk in a purely functional way here.

On Dec 5, 7:12 pm, Alex Baranosky <alexander.barano...@gmail.com>
wrote:
> Hi guys,
>
> I would like a function to be able to take an arbitrarily nested collection
> and return a sequence of all values of a given key, such as :name, that
> appears anywhere in the nested collection.
>
> Does anything like this already exist?
>
> Thanks for the help,
> Alex

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to