如何从clojure中的键列表的映射列表中找到匹配

  • 本文关键字:列表 映射 clojure clojure
  • 更新时间 :
  • 英文 :


我是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)))

(这与forfilter的方法有点类似。现在只有: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}}

相关内容

  • 没有找到相关文章

最新更新