查找地图是否包含多个键

Find if a map contains multiple keys

我是 Clojure 的新手,我想知道是否有一种方法可以测试地图是否有多个键。我注意到 contains? 只检查一个键

我正在尝试做的事情:

(def mario 
    {:position {:x 1 :y 2}
     :velocity {:x 2 :y 0}
     :mass 20})

;;Test if mario has a position and a velocity
(contains-many? mario :position :velocity) ;;true

;;Test if mario has a mass and a jump-height
(contains-many? mario :mass :jump-height) ;;false

基本上,clojure 库中是否有类似 contains-many? 的函数,如果没有,您将如何实现 contains-many? 函数?

我不知道有任何功能可以做到这一点。还需要定义您希望地图包含 every 键还是只包含 some 键。我选择了 every 案例,如果你想要 some 版本,只需将 every? 替换为 some?.

我的直接未优化版本是:

(defn contains-many? [m & ks]
  (every? #(contains? m %) ks))

已通过以下测试:

(deftest a-test
  (testing "Basic test cases"
    (let [m {:a 1 :b 1 :c 2}]
      (is (contains-many? m :a))
      (is (contains-many? m :a :b))
      (is (contains-many? m :a :b :c))
      (is (not (contains-many? m :a :d)))
      (is (not (contains-many? m :a :b :d))))))

编辑:使用 noisesmith 的建议进行了简化

已显示正确答案,但我想指出另一个优雅的解决方案,该解决方案假定了解地图值。当您确定它们是真实的时(即:不是 nil 也不是 false):

(every? m ks)

这是因为映射是(一元)函数,return 参数对应的值。但请注意 ({:x nil} :x) => nil.

这是另一个使用 clojure.set 的解决方案,适用于非真实值:

(require '[clojure.set :as set])

(defn contains-many? [m & ks]
  (empty? (set/difference (set ks) (set (keys m)))))

您可以利用 clojure.set/subset?

(clojure.set/subset?
  #{:position :velocity}
  (set (keys mario)))