2

我真的很喜欢使用contains?,因为它非常简洁易读。我想查看一个集合是否包含具有相同键值对的映射,该示例也具有其他键值对。我很确定contains?不会在这里工作。有替代方案吗?也许我必须写一个(我终于进入了心态!)。例如,如果我有

(def some-set #{{:foo "bar" :beep "boop"}{:foo "bar"} {:foo "bar" :hi "there"}})

什么是快速知道它是否有任何匹配{:foo "bar" :one "two"}的地图的方法:foo "bar"

4

3 回答 3

5

编辑:记住映射是键值向量的集合,这里是谓词的实现submap?

(defn submap?
  "Returns true if subm is a submap of m, false otherwise."
  [subm m]
  (every? (fn [[k v]] (= (get m k ::not-found) v)) subm))

此谓词可用于过滤任何集合:

(filter #(submap? {:a 1 :b 2} %) [{:a 1} {:a 1 :b 2 :c 3}])
=> ({:a 1, :b 2, :c 3})

原始答案

这个解决方案有效,但比我更新的答案慢,因为(set m)for largem

(defn submap?
  "Returns true if subm is a submap of m, false otherwise."
  [subm m]
  (let [kvs (set m)]
    (every? kvs subm)))
于 2021-04-16T22:09:31.917 回答
1

一种通用的方法是编写一个谓词,检查一个映射是否包含另一个映射。这可以通过select-keys仅获取具有某些键的地图来完成;使用keys地图中的进行比较,然后仅比较结果即可。

(def maps #{{:foo "bar" :beep "boop"} {:foo "bar"} {:foo "bar" :hi "there"} {:foo "baz"}})

(defn submap?
  [submap m]
  (= (select-keys m (keys submap)) submap))

(println
  (filter (partial submap? {:foo "bar"}) maps))
; → ({:foo bar, :beep boop} {:foo bar, :hi there} {:foo bar})

然而,这只是一个简单的顺序搜索。这并没有(而且 AFAIR 核心没有任何帮助)利用你的地图在一个集合中。另请注意,结果的顺序是未定义的,因为集合的顺序也是如此。

于 2021-04-16T19:59:57.183 回答
1

您可以在Tupelo 库中找到许多这种性质的谓词和相关的辅助函数,特别是:

  • 子图?
  • 子匹配?
  • 野战?
  • 野生亚匹配?

这些对编写单元测试特别有帮助。例如,您可能只关心某些字段,例如:body在测试 Web 服务器响应时,而您想忽略其他字段,例如 IP 地址或时间戳。

单元测试显示代码在运行。

于 2021-04-16T20:37:33.227 回答