(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)))
我们也可以通过2个item的窗口处理输入数据,在两个关键字之间插入
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}
clojure.spec 可用于表达处理缺失值的常规语言。在这里,我们为迷你语言定义了一个规范
::input
:
(require '[clojure.spec.alpha :as s])
(spec/def ::input (s/* (s/cat :k keyword? :v (s/? (complement keyword?)))))
conform
解析输入向量,并使用 into
ping 换能器将其放入 map
地图:
(defn parse-args [args]
(into {}
(map (juxt :k #(:v % true)))
(s/conform ::input args)))