【问题标题】:clojure find arbitrarily nested keyclojure 查找任意嵌套的键
【发布时间】:2016-02-25 15:29:00
【问题描述】:

Clojure 中是否有一种简单的方法(可能使用 specter)根据具有已知名称的任意嵌套键是否包含元素来过滤集合?

例如。 :

(def coll [{:res [{:a [{:thekey [
                          "the value I am looking for"
                      ...
                     ]
            }
           ]}
      {:res ...}
      {:res ...}
      ]}])

知道:a 可以有不同的名称,并且:thekey 可以嵌套在其他地方。 假设我想做:

 #(find-nested :thekey #{"the value I am looking for"} coll) ;; returns a vector containing the first element in coll (and maybe others)

【问题讨论】:

  • 集合必须是矢量和地图吗?还是允许其他类型?
  • 你能澄清/提供一个你想要的返回值的样本吗?
  • @Elogent 我只有向量、原始值和映射(即没有集合。这些值来自 mongodb + congomongo 数据库)。
  • @jmargolisvt 会做

标签: clojure specter


【解决方案1】:

使用拉链。 回复:

user> coll
[{:res [{:a [{:thekey ["the value I am looking for"]}]} {:res 1} {:res 1}]}]

user> (require '[clojure.zip :as z])
nil

user> (def cc (z/zipper coll? seq nil coll))
#'user/cc

user> (loop [x cc]
        (if (= (z/node x) :thekey)
          (z/node (z/next x))
          (recur (z/next x))))
["the value I am looking for"]

更新:

这个版本是有缺陷的,因为它不关心 :thekey 是映射中的键,还是向量中的关键字,所以它会给 coll [[:thekey [1 2 3]]] 提供不需要的结果。这是一个更新的版本:

(defn lookup-key [k coll]
  (let [coll-zip (z/zipper coll? #(if (map? %) (vals %) %) nil coll)]
    (loop [x coll-zip]
      (when-not (z/end? x)
        (if-let [v (-> x z/node k)] v (recur (z/next x)))))))

在回复中:

user> (lookup-key :thekey coll)
["the value I am looking for"]

user> (lookup-key :absent coll)
nil

假设我们在 coll 的向量中某处有相同的关键字:

(def coll [{:res [:thekey
                  {:a [{:thekey ["the value I am looking for"]}]}
                  {:res 1} {:res 1}]}])
#'user/coll

user> (lookup-key :thekey coll)
["the value I am looking for"]

这是我们需要的。

【讨论】:

  • 非常好用,没玩过拉链,我会尝试看看处理嵌套的情况谢谢。
  • 忘记检查z/end in loop,所以如果没有key就无限循环
猜你喜欢
  • 1970-01-01
  • 2018-04-12
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 1970-01-01
  • 1970-01-01
  • 2020-05-04
  • 2017-12-05
相关资源
最近更新 更多