如何在clojure中检查地图是否是另一个地图的子集?

szy*_*ski 3 clojure

我想编写一个函数来检查映射是否是另一个映射的子集.

用法的一个例子应该是:

(map-subset? {:a 1 :b 2} {:a 1 :b 2 :c 3})
=> true
Run Code Online (Sandbox Code Playgroud)

有原生方式吗?

小智 14

通过将地图转换为集合,您可以使用 clojure.set/subset?

(clojure.set/subset? (set {:a 1 :b 2}) (set {:a 1 :b 2 :c 3}))
=> true
Run Code Online (Sandbox Code Playgroud)

这将使每对地图成为集合中的一个元素

 (set {:a 1 :b 2 :c 3})
 => #{[:b 2] [:c 3] [:a 1]}
Run Code Online (Sandbox Code Playgroud)

因此,{:a 1 :b 3}不会是一个子集

(clojure.set/subset? (set {:a 1 :b 3}) (set {:a 1 :b 2 :c 3}))
=> false
Run Code Online (Sandbox Code Playgroud)


Mic*_*zyk 9

(defn submap?
  "Checks whether m contains all entries in sub."
  [^java.util.Map m ^java.util.Map sub]
  (.containsAll (.entrySet m) (.entrySet sub)))
Run Code Online (Sandbox Code Playgroud)

REPL演示:

(submap? {:foo 1 :bar 2 :quux 3} {:foo 1 :bar 2})
;= true
(submap? {:foo 1 :bar 2 :quux 3} {:foo 1 :bar 3})
;= false
(submap? {:foo 1 :bar 2} {:foo 1 :bar 2 :quux 3})
;= false
Run Code Online (Sandbox Code Playgroud)


Ash*_*her 5

另一种选择可能是:

(defn submap? [a b]
  (= a (select-keys b (keys a))))
Run Code Online (Sandbox Code Playgroud)

这只会检查第一张地图中键的权益。


kas*_*rma 2

对子集的含义做出假设(该定义的直接翻译):

(and (every? (set (keys m1)) (keys m2))  ;; subset on keys
     (every? #(= (m1 %)(m2 %)) (keys m2)))   ;; on that subset all the same values
Run Code Online (Sandbox Code Playgroud)