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

Reply via email to