Clojure 如何在深度嵌套的数据结构中查找元素?

Clojure 如何在深度嵌套的数据结构中查找元素?,clojure,tree-traversal,Clojure,Tree Traversal,我有这样的结构(它是解析JSON响应的结果): 所以它是一棵树子节点是节点的向量。每个节点都是一个具有a、b和子节点的映射 我正在尝试查找其b属性值为9的节点。 因此,查找的结果是: 我试图用树seq遍历结构: (tree-seq #(not-empty? % "children") identity structure) 但事实上,我得到了相同的结构。我希望得到一个节点序列,其中的关系是平坦的,然后我可以过滤序列 如何以惯用的方式做到这一点?你可以随意用拉链或走路让我大吃一惊。你可以得到想要

我有这样的结构(它是解析JSON响应的结果):

所以它是一棵树<代码>子节点是节点的向量。每个节点都是一个具有
a、b和子节点的映射

我正在尝试查找其
b
属性值为
9
的节点。 因此,查找的结果是:

我试图用
树seq
遍历结构:

(tree-seq #(not-empty? % "children") identity structure)
但事实上,我得到了相同的结构。我希望得到一个节点序列,其中的关系是平坦的,然后我可以过滤序列


如何以惯用的方式做到这一点?你可以随意用拉链或走路让我大吃一惊。

你可以得到想要的树,如下所示:

(def ts (mapcat (partial tree-seq #(contains? % "children") 
                                  #(get % "children"))
                your-data-structure))
mapcat
是必需的,因为您的输入数据结构包含多个根节点

例如。找到这样一个节点:

(first (filter #(= (get-in % ["a" "b"]) 9) ts))
;-> {"a" {"b" 9, "c" 10}, "children" []}
branch?
fn将在第一次迭代时接收整个向量作为参数,因此我使用了
vector?
谓词,但这是不必要的,因为我们可以使用简单的
notempty
函数来简化它,该函数对向量和映射都非常有效

(tree-seq 
  not-empty
  #(if (vector? %) % (% "children")) 
  data)

要在当前三个节点中搜索,还是也要在嵌套节点中搜索?结果应该是父节点(带子节点)或某些子节点?@fl00r我还需要搜索嵌套节点。所以,如果我在搜索b=9的节点,我想得到那个节点,包括它的子节点。
(tree-seq#(或(vector?%)(“children”))#(if(vector?%)(seq%)(“children”))数据。
?@fl00r这太好了!请你把它作为答案贴出来好吗?请您解释一下为什么
向量?
是if分支谓词的一部分?性能:分支?应该是谓词。可靠性:在tree seq的docstring中甚至没有提到逻辑真理。性能:向量?条件只适用一次。样式:#(not empty%)与not empty相同。@LeonGrapenthin您所说的:
“vector”条件只保存一次“
?@Chiron传递给该lambda的唯一向量是输入数据集。从这里,所有的孩子都是地图。这是因为输入数据集不是通用节点。它是子节点(或根节点,取决于您希望如何查看它)的集合。
(def data
  [{"a" {"b" 1 "c" 2} 
    "children" [{"a" {"b" 3 "c" 4} "children" []}]}
   {"a" {"b" 5 "c" 6} 
    "children" []}
   {"a" {"b" 7 "c" 8}
    "children" [{"a" {"b" 9 "c" 10} "children" []}]}])
(tree-seq 
  not-empty
  #(if (vector? %) % (% "children")) 
  data)