我是clojure新手。
有一个映射s1和一个向量s2
(def s1 {:params [{:param :begin_date
:name "begin date"
:dtk :date
:param_operand :single}
{:param :begin_num
:name "begin num"
:dtk :numeric
:param_operand :single}
{:param :begin_num2
:name "begin num2"
:dtk :numeric
:biparam_operand :single}]})
(def s2 [:begin_date :begin_num])
我试图找到s1与s2的匹配。即遍历s2中的每个元素并找到s1中的匹配项。如果匹配存在,检查类型为:dtk,如果类型为:date,则接受该映射。
这是我尝试过的代码,当我必须查找匹配是否存在时,只使用列表中的一个元素s2 -:begin_date
(defn test->map
[s1 s2]
(let [test-vec (->> s1
:params
(filter (fn [typet] (= (:param typet) :begin_date)))
first
:dtk)]
(when (= test-vec :date)
"done")))
如何修改上述函数,使其能够遍历整个元素列表并找到匹配项。TIA。
一种方法是使用keep
:
(defn match [k]
(->> s1
:params
(keep
(fn [{:keys [param] :as v}]
(when (= param k)
v)))
first))
或使用for
与:when
:
(defn lookup [k]
(first
(for [{:keys [param] :as v} (:params s1)
:when (= param k)]
v)))
(这与for
和filter
的方法有点类似。现在只有:when
进行过滤,我返回实际值而不是字符串"done"
。)
与结果:
(map lookup s2)
;; => ({:param :begin_date, :name "begin date", :dtk :date, :param_operand :single}
;; {:param :begin_num, :name "begin num", :dtk :numeric, :param_operand :single})
我个人会将当前的数据结构s1
转换为Clojure映射(例如通过reduce
)一次,这样您就可以通过键访问参数并使用select-keys
。这样你就不必在每次查找时遍历整个s2了。
(defn transform [s1]
(reduce
(fn [acc {:keys [param] :as v}]
(assoc acc param v))
{}
(:params s1)))
(transform s1)
;; => {:begin_date
;; {:param :begin_date, :name "begin date", :dtk :date, :param_operand :single},
;; :begin_num
;; {:param :begin_num, :name "begin num", :dtk :numeric, :param_operand :single},
;; :begin_num2
;; {:param :begin_num2,
;; :name "begin num2",
;; :dtk :numeric,
;; :biparam_operand :single}}
(select-keys (transform s1) s2)
;; => {:begin_date
;; {:param :begin_date, :name "begin date", :dtk :date, :param_operand :single},
;; :begin_num
;; {:param :begin_num, :name "begin num", :dtk :numeric, :param_operand :single}}