Использование спектра для преобразования значений, которые соответствуют ключу - PullRequest
0 голосов
/ 09 января 2019

Извините, если на этот вопрос был дан ответ в другом месте, но я не могу найти пример, который соответствует шаблону того, что я ищу. Я также, возможно, еще не полностью понимаю пути рекурсивного спектра.

Если у меня есть данные (явно с вложенным вектором):

{:a "1" :b "2" :c [ {:a "3" :b "4"} {:a "5" :b "6"} ]}

И я хотел бы применить функцию keyword ко всем значениям с помощью клавиши :a, чтобы получить:

{:a :1 :b "2" :c [ {:a :3 :b "4"} {:a :5 :b "6"} ]}

Наконец, я бы хотел, чтобы он был рекурсивным на произвольную глубину, а также обрабатывал векторный случай.

Я прочитал https://github.com/nathanmarz/specter/wiki/Using-Specter-Recursively, но я, должно быть, упускаю что-то критическое.

Спасибо всем, кто указывает мне правильное направление!

Ответы [ 2 ]

0 голосов
/ 09 января 2019
(use '[com.rpl.specter])
(let [input          {:a "1" :b "2" :c [{:a "3" :b "4"} {:a "5" :b "6"}]}
      desired-output {:a :1 :b "2" :c [{:a :3 :b "4"} {:a :5 :b "6"}]}
      FIND-KEYS      (recursive-path [] p (cond-path map? (continue-then-stay [MAP-VALS p])
                                                     vector? [ALL p]
                                                     STAY))]

    (clojure.test/is
        (= (transform [FIND-KEYS (must :a)] keyword input)
           desired-output)))
0 голосов
/ 09 января 2019

Не решение Spectre, но это легко сделать через clojure.walk/postwalk:

(ns demo.core
  (:require
    [clojure.walk :as walk] ))

(def data    {:a "1" :b "2" :c [{:a "3" :b "4"} {:a #{7 8 9} :b "6"}]})
(def desired {:a :1  :b "2" :c [{:a :3  :b "4"} {:a #{7 8 9} :b "6"}]})

(defn transform
  [form]
  (if (map-entry? form)
    (let [[key val] form]
      (if (and
            (= :a key)
            (string? val))
        [key (keyword val)]   ; can return either a 2-vector
        {key val}))           ; or a map here
    form))

(walk/postwalk transform data) => 

    {:a :1, :b "2", :c [{:a :3, :b "4"} {:a #{7 9 8}, :b "6"}]}

Я даже вставил не-строку для одного из значений :a, чтобы сделать его сложнее.

...