【问题标题】:clojure: filtering a vector of maps by keys existence and valuesclojure:通过键存在和值过滤映射向量
【发布时间】:2016-09-25 00:26:28
【问题描述】:

我有一张这样的地图矢量

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

我正在尝试定义一个函数,该函数接受 {"element1" 1 "element3" 6} 之类的映射(即:具有 n 个字段,或 {})并在 map1 中拟合映射,仅返回没有 @ 的映射987654325@ 和 consumes,或者与它们关联的数字小于与提供的映射中与该键关联的数字(如果提供的映射没有类似的任何键,则不会返回)

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

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

【问题讨论】:

  • 你好戴维斯!我编辑了问题以准确反映我在代码中遇到的问题

标签: clojure elementary-functions


【解决方案1】:

有两种方法可以看待此类问题:从外向内或从内向外。在使用嵌套结构时,仔细命名事物会很有帮助。例如,调用地图向量 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 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)

【讨论】:

  • 非常感谢您抽出宝贵时间帮助我解决这个问题!但是,我无法理解如何为您的函数提供过滤映射(即{"element1" 1 "element3" 6}),因为我只看到每个函数都有一个参数。我错过了什么?
  • keys-higher-than-values 函数正在检查传入的映射 m 中的每个键
  • 我的问题是如何运行这些函数?使用(filter comparisons map1) 将不起作用(因为它不应该,但我不明白我应该在哪里指定过滤图)
  • (filter comparisons map1) 是你应该做的。我编辑了答案以将所有部分放在一起。
  • 对不起,一定是误会了!在我问的问题中,“一个函数接受像 {"element1" 1 "element3" 6} 这样的地图并在 map1 中调整地图......”,我必须说我不完全理解你的代码,但是函数应该有 2 个参数:map1 和过滤映射
猜你喜欢
  • 1970-01-01
  • 2011-11-04
  • 2012-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-02
相关资源
最近更新 更多