I think the following function does what you want (I've also published it @ http://gist.github.com/449266 if you find Gists prettier):
(defn munge [vs] (if (== 1 (count (first vs))) (reduce into vs) (let [gs (group-by #(% 0) vs)] (map (fn [k v] {:data k :children v}) (keys gs) (->> (vals gs) (map (partial map #(subvec % 1))) (map munge)))))) A sample interaction at the REPL: user> (def test-data [[:a1 :b1 :c1] [:a1 :b1 :c2] [:a1 :b2 :c3] [:a1 :b2 :c4] [:a2 :b3 :c5] [:a2 :b3 :c6] [:a2 :b4 :c7] [:a2 :b4 :c8]]) #'user/test-data user> (pprint (munge test-data)) ({:data :a1, :children ({:data :b1, :children [:c1 :c2]} {:data :b2, :children [:c3 :c4]})} {:data :a2, :children ({:data :b3, :children [:c5 :c6]} {:data :b4, :children [:c7 :c8]})}) If you decide to go the "keyd by field value" route (no :data / :children), here's a simplified version to do it: (defn munge [vs] (if (== 1 (count (first vs))) (reduce into vs) (let [gs (group-by #(% 0) vs)] (zipmap (keys gs) (->> (vals gs) (map (partial map #(subvec % 1))) (map munge)))))) user> (pprint (munge test-data)) {:a2 {:b4 [:c7 :c8], :b3 [:c5 :c6]}, :a1 {:b2 [:c3 :c4], :b1 [:c1 :c2]}} Of course you cannot beat David's version for simple elegance if the format it produces is acceptable... Sincerely, Michał -- 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