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

时间:2013-12-06 10:19:27

标签: clojure

我想编写一个函数来检查地图是否是另一个地图的子集。

使用的一个例子应该是:

(map-subset? {:a 1 :b 2} {:a 1 :b 2 :c 3})
=> true

有原生方式吗?

6 个答案:

答案 0 :(得分:14)

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

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

这会使每对地图成为集合

中的一个元素
 (set {:a 1 :b 2 :c 3})
 => #{[:b 2] [:c 3] [:a 1]}

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

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

答案 1 :(得分:9)

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

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

答案 2 :(得分:3)

另一种选择可能是:

collection @courses => :courses
attributes :id, :Title, :Credits , :department_name 

这只会检查第一张地图中按键的等值。

答案 3 :(得分:1)

有许多方法可以解决您的问题。一个快速可行的解决方案是:

(defn contains-submap? [map-structure keys] 
  (every? (partial contains? map-structure) keys)) 

(contains-submap? {:a 1 :b 2 :c 3} (keys {:a 1 :b 2}))
true

例如,可以使用集合来完成。但正如@kasterma指出的那样,这取决于你原来的打算。

答案 4 :(得分:1)

假设子集的意思(该定义的直接翻译):

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

答案 5 :(得分:0)

假设您打算将键和值匹配...

  

有原生方式吗?

没有标准功能。我建议......

(defn map-subset? [a-map b-map]
  (every? (fn [[k _ :as entry]] (= entry (find b-map k))) a-map))

一些例子:

(map-subset? {:a 1 :b 2} {:a 1 :b 2 :c 3})
=> true

(map-subset? {:d 4} {:a 1 :b 2 :c 3})
=> false

(map-subset? {:a 3} {:a 1 :b 2 :c 3})
=> false

(map-subset? {:a nil} {})
=> false
  • 它只穿过它的第一个参数。
  • 正确处理nil值。

如果这些都不重要,请使用更优雅的版本,例如kasterma's