首页 > 解决方案 > 如何在第一个真正的谓词匹配的嵌套地图上退出 Clojure walk postwalk?

问题描述

我正在使用clojure.walk/postwalk将谓词与嵌套集合中的每个地图进行比较,并希望在第一个上以 true 退出true。我该怎么做?我可以通过它遍历整个数据结构,然后在true匹配时返回 true。

作为一个必然的问题,我想同样的问题可能适用于当一个人执行 amap而不是 a时postwalk

更新:这确实是一个疲倦/懒惰的问题;我应该提供一个代码示例。就是说,如果有人目前正​​在为我的半生不熟的问题制定答案,我会保留它。唯一比问一个更糟糕的事情是在有人好心开始提供帮助后将其删除。如果没有人回答,如果他们要求更好的问题,或者如果他们只是给我研究什么的建议,我会很满足。

标签: clojure

解决方案


你可能对我调用的这个函数感兴趣walk-seq。它在数据结构上返回一个惰性深度优先序列,然后您可以seek针对该数据结构找到第一个匹配项。我发现它在这里更可取,因为它不需要回调和异常来提前退出clojure.walk/postwalk


(defn walk-seq 
  "Returns a lazy depth-first sequence of all forms within a data structure."
  [form]
  (tree-seq coll? seq form))

(defn seek
  "Find the first element in the collection that matches pred,
   else returns not-found. Note that using seek can lead to
   poor performance and you should always use indexed data
   structures instead of multiple seeks over the same data."
  ([pred coll]
   (seek pred coll nil))
  ([pred coll not-found]
   (reduce (fn [nf x] (if (pred x) (reduced x) nf)) not-found coll)))

用法walk-seq


(walk-seq {:a [{:b -1} {:b 1}] :b 2})
=>
({:a [{:b -1} {:b 1}], :b 2}
 [:a [{:b -1} {:b 1}]]
 :a
 [{:b -1} {:b 1}]
 {:b -1}
 [:b -1]
 :b
 -1
 {:b 1}
 [:b 1]
 :b
 1
 [:b 2]
 :b
 2)

将两者结合起来:

(seek (every-pred number? pos?) (walk-seq {:a [{:b -1} {:b 1}] :b 2}))
=>
1

推荐阅读