Skip to content

Instantly share code, notes, and snippets.

@li1
Last active January 27, 2019 17:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save li1/5293da014fbd2017f4cc9fce8727f5ab to your computer and use it in GitHub Desktop.
Save li1/5293da014fbd2017f4cc9fce8727f5ab to your computer and use it in GitHub Desktop.
Transform 3DF pull paths into GraphQL-like nested maps
(ns merge.core)
(def unplanned-data
[[:loans :3 :amount 100]
[:loans :3 :from :1]
[:loans :3 :from :1 :name "a"]
[:loans :3 :observer :1]
[:loans :3 :observer :1 :name "a"]
[:loans :3 :observer :2]
[:loans :3 :observer :2 :name "b"]
[:loans :3 :observer :5]
[:loans :3 :observer :5 :name "c"]
[:loans :3 :to :2]
[:loans :4 :amount 200]
[:loans :4 :from :2]
[:loans :4 :from :2 :name "b"]
[:loans :4 :to :1]])
;; remove redundant short paths during planning phase
(def data
[[:loans :3 :amount 100]
[:loans :3 :from :1 :name "a"]
[:loans :3 :observer :1 :name "a"]
[:loans :3 :observer :2 :name "b"]
[:loans :3 :observer :5 :name "c"]
[:loans :3 :to :2]
[:loans :4 :amount 200]
[:loans :4 :from :2 :name "b"]
[:loans :4 :to :1]])
; example of intended output
(def target-data
{:loans
[{:amount 100
:to :2
:from [{:name "a"}] ;; vectors since an id assumes that there could be more
:observer [{:name "a"}
{:name "b"}
{:name "c"}]}
{:amount 200
:to :1
:from [{:name "b"}]}]})
(defn jog [d]
(reduce (fn [acc x] (assoc-in acc (pop x) (peek x))) {} d))
(defn shove
"takes a jogged map and recursively shoves it together. This way,
the eid levels are 'squashed' into vectors (cf. graphql)."
[m]
(if (map? m)
(reduce (fn [acc [k v]]
(let [to-add (if (map? v)
(map shove (vals v))
v)]
(assoc acc k to-add))) {} m)
m))
(comment
(shove (jog data)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment