Fork me on GitHub
Lone Ranger02:09:39

specific and general question. General question: where does one go to level up in specter? I feel like I've already tapped out on talks/tutorials and I know I'm only scratching the surface. Case in point -- Specific question: given

(def contrived-data {:time 1535940129129
                       :data [{:a [{:start 389
                                    :stop  456}]}
                              {:b [{:start 113
                                    :stop  889}]}]})
I'm attempting to sort by :start. It's blessedly simple to select the values via
(sm/select [:data s/ALL s/MAP-VALS s/ALL :start] contrived-data)
my intuition to do the operation would be
(sm/transform [:data s/ALL s/MAP-VALS s/ALL :start] sort contrived-data)
but I realized my thinking may have gone awry somewhere along the way


@goomba what do you want the result of that transform to be?

Lone Ranger02:09:24

sorry, should've posted that

Lone Ranger02:09:42

as in, :b should come first because its :start value is lower


what if the inner collection has multiple :start values?


use the lowest?

Lone Ranger02:09:12

hadn't thought that far ahead with my contrived example

Lone Ranger02:09:52

it's the fact that the keys :a and :b "pre-fix" the data makes any sort of normal update-in/`sort-by` completely unusable, at least with any sort of elegance/performance

Lone Ranger02:09:12

but I encounter this problem all the time


you can use something like (fn [m] (reduce min (traverse [MAP-VALS ALL :start] m)) for a "keyfn" to sort-by


and then (transform :data #(sort-by keyfn %) data)


beware that sort-by will change that vector to a list

Lone Ranger02:09:15

ohhhh mannn that is cooooolllllll 😄

Lone Ranger02:09:11

thank you! how did you... well, I guess because you wrote it, I would've thought to use select instead of traverse


always use traverse if all you'll be doing is a reduce over the result


more efficient since no intermediate list is materialized

Lone Ranger02:09:05

🙏 fantastic. Thanks again.