Dear all, I've been playing around with Meander Epsilon a bit, and I've stumbled upon a problem that feels like trivially solvable but I just couldn't break it. So, noobie question. I'm looking to do kinda like a join, and flatten thing on a vector in a nested map... any help would be highly appreciated!
(def db {:items [{:id 1 :labels [1 2 3]}
{:id 2 :labels [2]}
{:id 3 :labels []}
{:id 4 :labels nil}
{:id 5 }]
:labels [{:id 1 :name "one"}
{:id 2 :name "two"}
{:id 3 :name "three"}
{:id 4 :name "four"}]})
(defn flatten-labels [db]
???)
;; =>
;; {:items
;; [{:id 1 :labels ["one" "two" "three"]}
;; {:id 2 :labels ["two"]}
;; {:id 3 :labels []}
;; {:id 4 :labels []}
;; {:id 5 :labels []}]}
I'm in a meeting now and going to be grabbing lunch. But will hopefully have some time to play with this after that.
(m/rewrite db
{:labels ?labels
:items [{:id !id :labels (m/or nil [!xs ..!n])} ..?m]}
{:items [{:id !id :labels [(m/cata [!xs ?labels]) ..!n]} ..?m]}
[?id (m/gather {:id ?id :name !label})] !label)
There is a lot going on here. First we have nested repeating going on. So in order to capture that I used our capturing repeats [!xs ..!n]
and ..?m
. Then we have to deal with nil, so I used an m/or
.
But the big thing here is the cata
. If you haven't seen cata, it is like recur. So now we have two patterns. We pass back a vector with the id we want to find and then use gather to search for it.
I'd recommend changing your labels to be a map of id to string value. But maybe you want to have the possibility of duplicates? If so you could change this to handle this pretty easily too.
I know that was a pretty quick description, so feel free to ask and I can describe things in more detail.There could maybe be a more direct way of doing this, but I definitely can't think of one given the nested repeats going on.
Thanks @jimmy, appreciated! I'll work my way through this and might get back if I'd get lost... 😉