(defn parse-args
([args]
(parse-args args {}))
([[fst sec & more] rst]
(let [value? (fn [x] (and (not (keyword? x))
(not (map? x))))]
(cond
(and (keyword? fst)
(keyword? sec)) (parse-args (cons sec more) (merge rst {fst true}))
(and (keyword? fst)
(value? sec)) (parse-args more (merge rst {fst sec}))
:else rst
))))
*я новичок в clojure
например, есть vec, как показано ниже:
[:enchant :type "Fire Aspect" :level 123]
попробуйте преобразовать его в:
{:enchant true :type "Fire Aspect" :level 123}
обратите внимание, что исходный vec был каким-то образом «перемежается»
но не каждый ключ имеет свое «значение» (например, :enchant
)
и я просто хочу узнать их и рассматривать как логическое значение
с true
в качестве значения по умолчанию
я пытался использовать:
(defn parse-arg [args toggle-coll]
(let [is-value? #(not (and (keyword? %)
(map? %1)))]
(reduce (fn [k1 k2]
(merge
(cond
(and (keyword? k1)
(keyword? k2)) ({} {k1 true})
(and (keyword? k1)
(is-value? k2)) ({} {}) ; and soon i found this method is difficult and clumsy
(and (map? k1)
(is-value? k2)) ({} {})
(and (map? k1)
(keyword? k2)) ({} {})
;; omitted)
)
)
args)))
clojure.spec можно использовать для выражения обычного языка для обработки пропущенных значений. Здесь мы определяем спецификацию ::input
для мини-языка:
(require '[clojure.spec.alpha :as s])
(spec/def ::input (s/* (s/cat :k keyword? :v (s/? (complement keyword?)))))
Затем мы можем проанализировать входной вектор с помощью соответствия и поместить его в карту с помощью картыпреобразователь пинга:
(defn parse-args [args]
(into {}
(map (juxt :k #(:v % true)))
(s/conform ::input args)))
мы также можем обработать входные данные по окнам из 2-х элементов и вставить true
между двумя ключевыми словами:
(defn parse-args [data]
(->> (concat data [::end])
(partition 2 1)
(mapcat (fn [[a :as pair]]
(if (every? keyword? pair)
[a true]
[a])))
(apply hash-map)))
::end
kv добавляется для обработки оборванного ключевого слова в конце последовательности, если таковое имеется.
user> (parse-args [:a :b 1 :c 10 :d])
;;=> {:c 10, :b 1, :d true, :a true}
Хорошее решение! Я добавил что-то похожее, но решил снова удалить его, потому что забыл об обработке этого висящего ::end
.
@amalloy, это не дубликат преобразования seq -> hash-map, речь идет о выводе отсутствующих значений во входном векторе со значением по умолчанию
true