2

I hava a data structure that looks like this:

(def conf 
  { :devices [{:alias "OSC Sender",
               :name "OSC Sender",
               :ins [{:name "xpos", :type :int, :mutable true}]},
              {:alias "const2", :name "const",
               :outs [{:name "out", :type :int}]}],
    :connections {"const2.out" "OSC Sender.xpos"},
    :layout [{:alias "const2",
              :x 72.12447405329594,
              :y 99.88499298737729},
             {:alias "tick",
              :x 82.5732819074334,
              :y 133.91374474053296},
             {:alias "OSC Sender",
              :x 185.17741935483872,
              :y 113.90322580645162}]})

I would like to join maps in :devices and :layout by key (specifically :alias) to enrich the devices with layout information.

Right now I cobbled the following solution:

(map (partial reduce merge) (vals (group-by :alias (concat (:devices conf) (:layout conf)))))

Is that an idiomatic join or is something else preferable?

Cheers

Rom1
  • 3,167
  • 2
  • 22
  • 39

1 Answers1

7

You can use the join function from the clojure.set namespace:

(clojure.set/join (conf :devices) (conf :layout) {:alias :alias})

Note that the return value is a set. Omitting the final argument results in a natural join; see (doc clojure.set/join) for details.

Michał Marczyk
  • 83,634
  • 13
  • 201
  • 212
  • marczyk, any idea about outer joins, left,right, n full ? If I want to keep the dictionary on the left set as it is, if it has no match on the other side ? – Amogh Talpallikar Dec 06 '13 at 17:25
  • `clojure.set` doesn't provide any outer join functions, but of course one can write one's own. That's a subject for a separate question, though; in fact, one that has been asked before, for example [here](http://stackoverflow.com/questions/13009939/outer-join-in-clojure). – Michał Marczyk Dec 07 '13 at 18:41