2013-03-21 83 views
2

我想检查矢量[:e [:a :b] [:c :d]]中给出的每个键是否存在于映射中。如何检查映射中是否存在嵌套键

{:e 2 :a {:b 3} :c {:d 5}}

我可以写下面的检查 -

(def kvs {:e 2 :a {:b 3} :c {:d 5}})  
(every? #(contains? kvs %) [[:e] [:a :b] [:c :d]]) 

然而,由于含有犯规检查低沉,像更新,在不关键的一条水平上面会失败。我如何完成上述?

回答

1

下做它 -

(every? #(get-in kvs %) [[:e] [:a :b] [:c :d]]) 

任何其他的答案也欢迎!

+2

这将返回false,如果一个关键是有,但它有一个无/错误的值 – Ankur 2013-03-21 05:39:50

+0

这将不起作用,请检查以下内容(每个?#(get-in kvs%)[[:e] [:a:c:b] [:c:d]]) )'。按键顺序与地图上的“进入”有关。 – 2013-03-21 05:44:46

+0

@KugathasanAbimaran:排序是问题的一部分,[:a:b]表示检查地图是否有:key和:b内的值:密钥 – Ankur 2013-03-21 06:09:28

1

如何:

(every? #(if (vector? %) 
      (contains? (get-in kvs (drop-last %)) (last %)) 
      (contains? kvs %)) [:e [:a :b] [:c :d]]) 
+0

向下投票?谨慎评论? – Ankur 2013-03-21 06:38:22

+0

+1努力Ankur! – murtaza52 2013-03-21 06:47:50

3

上穆尔塔扎的基本方法,在MAP零或假值也可以工作的改进:

(defn contains-every? [m keyseqs] 
    (let [not-found (Object.)] 
    (not-any? #{not-found} 
       (for [ks keyseqs] 
       (get-in m ks not-found))))) 

user> (contains-every? {:e 2 :a {:b 3} :c {:d 5}} 
         [[:e] [:a :b] [:c :d]]) 
true 
user> (contains-every? {:e 2 :a {:b 3} :c {:d 5}} 
         [[:e] [:a :b] [:c :d :e]]) 
false 
+0

我建议交换'defn'和'let'行,这样'not-found'只创建一次,而不是每个函数的调用。 – dimagog 2013-03-21 19:00:07

+0

@dimagog我可能会在自己的代码中这样写,但它似乎是clojure程序员不喜欢的风格。分配一个新对象是JVM能够做的最快的事情之一,因此以“慢”的方式来做它并不是非常昂贵。你停在哪里?真的,我们应该关闭'#{not found}'。到那个时候,这个函数看起来非常难看,因为它可以改善性能。 – amalloy 2013-03-21 23:11:14