Hi, I'm trying to integrate meander in my project and wandering how to transform
{:AAA {:prop1 ["A" "B"] :prop2 [1 2 3 4]}
:BBB {:prop1 ["X" "Y" "Z"] :prop2 [8 9]}}
into
{:prop1 {:AAA ["A" "B"]
:BBB ["X" "Y" "Z"]}
:prop2 {:AAA [1 2 3 4]
:BBB [8 9]}}
I'm using it for the first time, so a bit struggling with it.
The best I end up is this:
(m/search {:AAA {:prop1 ["A" "B"] :prop2 [1 2 3 4]}
:BBB {:prop1 ["X" "Y" "Z"] :prop2 [8 9]}}
{?topkey {:prop1 ?prop1v :prop2 ?prop2v}}
{:prop1 {?topkey ?prop1v}
:prop2 {?topkey ?prop1v}})
; => {:prop1 {:AAA ["A" "B"]}, :prop2 {:AAA ["A" "B"]}}
; {:prop1 {:BBB ["X" "Y" "Z"]}, :prop2 {:BBB ["X" "Y" "Z"]}}
Is there a way to perform deep merge out of the box here?@grzegorz.rynkowski Welcome. Iβve seen this problem before and I would say that Meander alone would not be a good fit. The recommendation for this problem is to use a combination of Meander and Clojure.
(def result
(m/search {:AAA {:prop1 ["A" "B"]
:prop2 [1 2 3 4]}
:BBB {:prop1 ["X" "Y" "Z"]
:prop2 [8 9]}}
{?a {?b ?c}}
[[?b ?a] ?c]))
;; =>
([[:prop1 :AAA] ["A" "B"]]
[[:prop2 :AAA] [1 2 3 4]]
[[:prop1 :BBB] ["X" "Y" "Z"]]
[[:prop2 :BBB] [8 9]])
(reduce (fn [m [p v]] (assoc-in m p v)) {} result)
;; =>
{:prop1 {:AAA ["A" "B"], :BBB ["X" "Y" "Z"]},
:prop2 {:AAA [1 2 3 4], :BBB [8 9]}}
Comparing the m/search
to what you might do in Clojure (input is example map):
(mapcat (fn [[a m]] (map (fn [[b c]] [[b a] c]) m)) input)
(m/search input {?a {?b ?c}} [[?b ?a] ?c])
To produce the intermediate sequence of [[b a] c]
.
A quick (time (dotimes [n 1000] (doall form)))
between the two lines above, on my machine, show that Meander is, on average, about 5ms slower than vanilla Clojure. Depending on your goals that could be acceptable.
Certainly I would say the m/search
is easier to understand than the combination of mapcat
and map
. If you have more cases to consider, for example, a key that has a non map value, Meander can adjust to that easily.
(m/search (assoc input :CCC "Yarn")
{?a {?b ?c}}
[[?b ?a] ?c]
{?a ?c}
[[?a] ?c])
;; =>
(,,, [[:CCC] "Yarn"])
@markaddleman Do you still have the within
examples lying around? Slack has truncated that discussion and I wanted to move it GH.
I'm using within
in a dev project. I can easily reconstruct examples
If youβre able to open a discussion on GH, do so, if not, I shall create one for this topic. π
Sure I'm picking that project back up later today or tomorrow and I'll open an issue with it
I want to reserve issues for items that have an action plan or bugs, and use discussions for ideas and, um, discussions. π
π Sure
@noprompt I'm out for the rest of the week. I'll definitely do a PR when I get back.
OK. I look forward to it. Have a great week! π
Thanks for the thorough explanation. Certainly it is easier to understand than mapcat + map, and quite elegant, especially for a generic transformations when properties names are irrelevant. Expressivity was the key reason why tried to use Meander at the first place. Although in my particular case, I ended up with simple reduce:
(reduce (fn [{:keys [prop1 prop2]} [k v]]
{:prop1 (assoc prop2 k (:prop1 v))
:prop2 (assoc prop1 k (:prop2 v))}) {} input))
It is just simpler, more concise, and in this particular case where properties names are known, it is easier to reason it.
I will keep Meander in mind though. It looks like a great tool.@noprompt Maybe the clojurians archive can help here: https://clojurians-log.clojureverse.org/meander/ I think it's indexable by Google, so it might be possible to search through it
That makes perfect sense to me. π
thx
I know this is overdue. And maps will get the same treatment.
I suspect this feature will be more useful for rewriting.