clojure:按键存在和值过滤地图矢量

时间:2016-05-26 20:26:16

标签: clojure elementary-functions

我有一个像这样的地图矢量

  (def map1 
    [{:name "name1"
      :field "xxx"}
     {:name "name2"
      :requires {"element1" 1}}
     {:name "name3"
      :consumes {"element2" 1 "element3" 4}}])

我试图定义一个接收{"element1" 1 "element3" 6}等地图的函数(即:带有n个字段,或{})并在map1中更新地图,返回只有那些没有requiresconsumes,或者与它们关联的数字低于与提供的地图中的该关键字相关联的数字(如果提供的地图没有这样的关键,它没有被退回)

但我没有掌握如何处理地图递归循环和过滤

(defn getV [node nodes]

  (defn filterType [type nodes]
    (filter (fn [x] (if (contains? x type)
                    false ; filter for key values here
                    true)) nodes))

  (filterType :requires (filterType :consumes nodes)))

1 个答案:

答案 0 :(得分:1)

有两种方法可以看待这样的问题:从外到内或从内到外。在使用嵌套结构时,仔细命名是非常有用的。例如,调用map map1的向量可能会增加混乱。

从外部开始,您需要一个谓词函数来过滤列表。此函数将地图作为参数,并由过滤函数使用。

(defn comparisons [m]
   ...)

(filter comparisons map1)

我不确定我是否准确理解了比较,但似乎至少有两种口味。第一个是查找没有的地图:requires或:使用密钥。

(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 how can I convert a String to a number?

找到
(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)