On Sun, Dec 5, 2010 at 9: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?

It does now:

(defn values-of [k coll]
  (if-let [s (try (seq coll) (catch Exception _ nil))]
    (let [not-found (Object.)
          v (if (associative? coll) (get coll k not-found) not-found)
          v (if-not (= v not-found) [v])
          vs (map #(values-of k %) s)]
      (apply concat v vs))))

user=> (values-of :k [1 2 {:k 3 :l 4} 5 #{6} [[{:k 2}] {:k {:a 3 :k 7}}]])
(3
 2
 {:a 3, :k 7}
 7)

It won't quite work perfectly for java.util collections, specifically
because (associative? (java.util.HashMap.)) comes back false for some
reason. If the only maps are Clojure maps it should work. If the key
is an integer it will count vector entries at that index as values. It
should work if a map *key* is itself a structure that contains the key
and it should also correctly collect nils:

user=> (values-of :k {{:k 3} 'foo :k nil})
(nil 3)

-- 
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