last question for now 🙏 can you help me combine this into one path? i want to filter on cost type :labor , then sum labor hours by category. getting tripped up on the group-by.
(def -line-items
[{:line-item/cost-type :labor
:line-item/category "Piping"
:labor/total-hours 5}
{:line-item/cost-type :labor
:line-item/category "Sheet Metal"
:labor/total-hours 8}
{:line-item/cost-type :labor
:line-item/category "Piping"
:labor/total-hours 7}
{:line-item/cost-type :material
:line-item/category "Piping"
:material/cost 500}
{:line-item/cost-type :material
:line-item/category "Sheet Metal"
:material/cost 300}
{:line-item/cost-type :labor
:line-item/category "Sheet Metal"
:labor/total-hours 4}])
;; filter on cost type :labor, then sum labor hours by category
(->> -line-items
(sp/select [sp/ALL (comp #{:labor} :line-item/cost-type)])
(group-by :line-item/category)
(sp/transform [sp/MAP-VALS (sp/view #(sp/select [sp/ALL :labor/total-hours number?] %))]
#(reduce + 0 %)))
;; => {"Piping" 12, "Sheet Metal" 12}
i tried copying this from examples but i'm misunderstanding how group-by-nav works.
(sp/defnav group-by-view [key]
(select* [this structure next-fn]
(next-fn (group-by key structure)))
(transform* [this structure next-fn]
(next-fn (group-by key structure))))
(defn group-by-nav [f] (sp/path (group-by-view f) sp/ALL sp/LAST))
(->> -line-items
(sp/transform [sp/ALL (comp #{:labor} :line-item/cost-type)
(group-by-nav :line-item/category)
sp/MAP-VALS (sp/view #(sp/select [sp/ALL :labor/total-hours number?] %))]
#(reduce + 0 %)))just for completeness, i came up with a solution that uses group-by-view. any suggestions would be appreciated.
(sp/transform [(group-by-view :line-item/category)
sp/ALL
(sp/collect-one sp/FIRST)
(sp/collect
sp/LAST
sp/ALL
(comp #{:labor} :line-item/cost-type)
:labor/total-hours)]
(fn [k v v2]
[k (reduce + 0 v)])
-line-items)
nevermind, i found a better approach that doesn't involve group-by. seems like group-by can be a bit of an antipattern when applying specter