On Sun, Dec 5, 2010 at 10:03 PM, Ken Wesson <kwess...@gmail.com> wrote: > 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.
This should work even for Java collections including maps: (defn values-of [k coll] (if (instance? java.util.Map$Entry coll) (recur k [(key coll) (val coll)]) (if-let [s (try (seq coll) (catch Exception _ nil))] (let [not-found (Object.) v (if (or (associative? coll) (instance? java.util.Map 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 (doto (java.util.HashMap.) (.put :k "foo"))) ("foo") user=> (values-of :k (doto (java.util.HashMap.) (.put {:k 3} "foo"))) (3) The new if at the start is because Clojure doesn't treat non-Clojure Map$Entries as equivalent to [key val] so I turn all Map$Entries into such vectors manually. As you can see, it will delve into both the keys and the values of even java.util Maps now. -- 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