有两种方法可以看待这样的问题:从外向内或从内向外。在使用嵌套结构时,仔细命名事物会很有帮助。例如,调用地图向量 map1 可能会增加混乱。
从外部开始,您需要一个谓词函数来过滤列表。此函数将地图作为参数,并由过滤器函数使用。
(defn comparisons [m]
...)
(filter comparisons map1)
我不确定我是否完全理解这些比较,但似乎至少有两种口味。首先是寻找没有 :requires 或 :consumes 键的映射。
(defn no-requires-or-consumes [m]
...)
(defn all-keys-higher-than-values [m]
...)
(defn comparisons [m]
(some #(% m) [no-requires-or-consumes all-keys-higher-than-values]))
然后是定义各个比较函数的问题
(defn no-requires-or-consumes [m]
(and (not (:requires m)) (not (:consumes m))))
第二个更复杂。它在一个或两个内部映射上运行,但在两种情况下的行为是相同的,因此可以将实际实现推到另一个级别。
(defn all-keys-higher-than-values [m]
(every? keys-higher-than-values [(:requires m) (:consumes m)]))
比较的关键是查看地图关键部分中的数字与值。将细节向下推一个级别给出:
(defn keys-higher-than-values [m]
(every? #(>= (number-from-key %) (get m %)) (keys m)))
注意:我在这里选择了 >= 以便示例数据中的第二个条目通过。
那只剩下拉动钥匙串的数量了。如何做到这一点可以在In Clojure 中找到如何将字符串转换为数字?
(defn number-from-key [s]
(read-string (re-find #"\d+" s)))
将所有这些串在一起并针对示例数据运行会返回第一个和第二个条目。
把所有东西放在一起:
(defn no-requires-or-consumes [m]
(and (not (:requires m)) (not (:consumes m))))
(defn number-from-key [s]
(read-string (re-find #"\d+" s)))
(defn all-keys-higher-than-values [m]
(every? keys-higher-than-values [(:requires m) (:consumes m)]))
(defn keys-higher-than-values [m]
(every? #(>= (number-from-key %) (get m %)) (keys m)))
(defn comparisons [m]
(some #(% m) [no-requires-or-consumes all-keys-higher-than-values]))
(filter comparisons map1)