And here is the final piece of working code, which we're using to transform results from Korma when we join a has one or belongs to association.
(def ^:private rel-attribute-pattern #"(.*)--(.*)$") (defn- nested-key [k] (some-> (re-matches rel-attribute-pattern (name k)) second keyword)) (defn nest-relations "Walks the given hash-map, and moves any keys of the form <relation>--<attribute> into a nested hash-map." [m] (let [grouped (group-by (fn [[k _]] (or (nested-key k) ::top)) m) top (::top grouped) remove-rel #(str/replace % rel-attribute-pattern "$2")] (-> (reduce-kv #(assoc % %2 (util/update-keys (into {} %3) remove-rel)) {} grouped) (dissoc ::top) (merge (into {} top))))) This can obviously be refactored and optimised, but does the job for now. Thank you very much for your help Mr. foo.bar. On Thursday, 16 January 2014 14:40:24 UTC, James wrote: > > Whoops… that's missing an all important (merge (into {} top)). > > On Thursday, 16 January 2014 14:36:45 UTC, James wrote: >> >> Thanks for the pointers. I've gotten as far as grouping the keys by the >> prefix using `group-by`, and added clunky support for keys that aren't >> nested like so: >> >> ``` clj >> (defn- nested-key [k] >> (some-> (re-matches #"^(.*)--(.*)$" (name k)) >> second >> keyword)) >> >> (defn nest-relations >> "Walks the given hash-map, and moves any keys of the form >> <group>--<key> into a nested hash-map." >> [m] >> (let [grouped (group-by (fn [[k _]] (or (nested-key k) ::top)) m) >> top (::top grouped)] >> (-> grouped >> (dissoc ::top) >> (merge top)))) >> ``` >> >> I end up with vectors instead of hash-maps, and I'm particularly happy >> with the code, but it's getting there. >> >> On Thursday, 16 January 2014 13:58:45 UTC, Jim foo.bar wrote: >>> >>> You could do something like this: >>> >>> >>> (def v {:a--id 1 :a--name "A" :b--id 2 :b--name "B"}) >>> >>> (group-by #(-> % first str second str keyword) v) >>> >>> =>{:b [[:b--name "B"] [:b--id 2]], :a [[:a--id 1] [:a--name "A"]]} >>> >>> (reduce-kv #(assoc % %2 (into {} %3)) {} *1) >>> >>> => {:a {:a--id 1, :a--name "A"}, :b {:b--name "B", :b--id 2}} >>> >>> all that's left is the names in the inner map... >>> >>> HTH, >>> >>> Jim >>> >>> >>> On 16/01/14 13:46, James Conroy-Finn wrote: >>> > Hello all, >>> > >>> > I've found myself stuck trying to move matching keys in a hash into a >>> > nested hash. >>> > >>> > For example,: >>> > >>> > {:a--id 1 :a--name "A" :b--id 2 :b--name "B"} ;=> {:a {:id 1 :name >>> > "A"} :b {:id 2 :name "B"}} >>> > >>> > I've tried `clojure.walk`, I've tried building the args to `assoc-in`, >>> > and using `apply`. I honestly feel like I'm missing something really >>> > obvious, like something with group-by. >>> > >>> > Any tips would be greatly appreciated. I'll keep hammering away. >>> > -- >>> > -- >>> > You received this message because you are subscribed to the Google >>> > Groups "Clojure" group. >>> > To post to this group, send email to clo...@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+u...@googlegroups.com >>> > For more options, visit this group at >>> > http://groups.google.com/group/clojure?hl=en >>> > --- >>> > You received this message because you are subscribed to the Google >>> > Groups "Clojure" group. >>> > To unsubscribe from this group and stop receiving emails from it, send >>> > an email to clojure+u...@googlegroups.com. >>> > For more options, visit https://groups.google.com/groups/opt_out. >>> >> -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.