Fork me on GitHub
#specter
<
2022-06-17
>
pdmct05:06:14

Hi, I am new to spectre and trying to use it to transform some ugly nested xml to a nicer edn format. I am stuck non trying to select values for keys that are in a map with a specific val (of a different key)

[{:piTypes
  ({:piType "10",
    ::name "PI_TYPE_1"},
    {:piType "20",
    :name "PI_TYPE_2"})]
  :piTypesCount
  ({:piTypeCount "1",
    :name "PI_TYPE_1"}
   {:piTypeCount "1",
    :name "PI_TYPE_2"})}]
My question is: Is it possible with spectre to select piType value (ie. “10”) where :name == “PI_TYPE_1" in the above example? or all maps with a given value? eg all maps containing k/v {:name “PI_TYPE_1”}?

pdmct06:06:49

ok, working through this I have come up with (if the above structure is called ‘groups’:

(defn select-maps [xrel m]
  ((clojure.set/index xrel (keys m)) m))

(select [ALL :piTypes ALL (pred #(select-maps (vector %) {:name "PI_TYPE_1"})) :piType] groups) => ["10"]
is there a better way than this?

rolt08:06:17

[ALL :piTypes ALL (pred #(= "PI_TYPE_1" (:name %))) :piType]

pdmct08:06:47

Thanks, yes that's an overly complex pred for what it is doing

pdmct07:06:43

on a slightly related note. Suppose that I have 2 variations of a structure:

(def one-child [{:a {:b {:c 2}}}])
(def two-children [{:a {:b [{:c 3}{:d 4}]}}])

(select [ALL :a :b (pred #(contains? % :c)) :c] one-child)
=> [2]
(select [ALL :a :b ALL (pred #(contains? % :c)) :c] two-children)
=> [3]
I want to select :c from both variations of these — when there are multiple children in a list I need to add the ALL navigator — what is the best way to determine whether the result at that point is a list or a map in this case and add the ALL into the selector? Is there a built-in method for dealing with this?

rolt08:06:21

you could use if-path or cond-path

pdmct10:06:54

thanks, will take a look at these