I am looking for what is idiomatic Clojure… that is to say, I know how to do this, but I’m looking for something that is a beautiful piece of code, as I think there must be an elegant way of expressing this in Clojure.
My friend, the clarity with which you must understand Clojure, to suggest what you suggested, is impressive. I already doubt that anybody can do better!
I want to suggest that the reason why I am spending time figuring out how to do this rather basic data maniuplation, after years of learning Clojure, as something holding our language back.
No group-by, just single-pass using reduce/update-in and map. seq and transducer versions. I really wish clojure.core had injected function arity information in fn (actually fn* I think) forms so we could dispense with the need for completing entirely and just infer it from the arities provided.
I bet meander or similar libraries (maybe specter or even malli) offer some really nice declarative ways to do this, but whether they are idiomatic is up for debate.
The best friend of update-in is probably fnil, that makes it very convenient to initialize with some initial value when nil. (fnil conj []) intializes a vector when reaching an empty key.