assuming we have some function f that returns a value that can be used as a dict key:
d = defaultdict(set)
for x in xs:
d[f(x)].add(x)
The structure will probably look something like this, but I can't figure out how to a) provide a default value and b) merge with the existing value
(defn build-maps [xs]
(let [inverse-map {}]
(reduce (fn [im x]
(let [y (f x)
im' (assoc im y x)] ; want to add x to a set
im')) inverse-map xs)))
update, the following seems to work
(defn build-maps [xs]
(let [inverse-map {}]
(reduce (fn [im x]
(let [y (f x)
new-im (assoc im y (set/union (im y) #{x}))]
new-im)) inverse-map xs)))
The way I would write this is:
(apply merge-with into
(for [x xs]
{(f x) #{x}}))
But if you wanted something closer to your reduce-based plan, you could write:
(reduce (fn [m x]
(update m (f x) (fnil conj #{}) x))
{}, xs)