在 Clojure 中递归调用具有特定关键字的函数
Recursively calling function with specific keyword in Clojure
我正在尝试递归调用参数为 node :type
folder
的函数,使用 if
语句有条件地过滤掉它们。但是我收到错误:
Uncaught Error: No item :type in vector of length 3
我认为这可能是因为 :children
向量为空,但即使其中有 :type
属性,我仍然会收到错误消息。这个错误有点神秘,我看不到没有 :type
关键字的矢量。
这是我的代码:
(defn dispatch-nodes-to-state [node & {:keys [depth] :or {depth 0}}]
(re-frame/dispatch [:set-nodes (conj {:depth depth} node)])
(if (= (node :type) "folder")
(do
(println "It's a folder")
(recur (node :children) (inc depth)))
(println "it's a file")))
(defn traverse-tree [nodes]
(run! dispatch-nodes-to-state nodes))
(defn get-file-tree []
(go (let [file-tree (<! (http/get API-URL request-opts))]
(traverse-tree (get-in file-tree [:body :root])))))
代码有明显错误吗?
这是我正在遍历的数据结构的片段。提前致谢:
[{:depth 0, :type folder, :empty false, :name My Documents, :children [{:type file, :name My Text 1, :extension .txt, :preview In ipsum est, faucibus ac tempor vel, tincidunt ac leo. Vestibulum quis odio nisl. Nulla auctor erat a sem ullamcorper vulputate. Fusce efficitur tempus nulla, eget suscipit tortor imperdiet nec. Aenean finibus, ipsum ut pulvinar euismod, neque tellus vestibulum justo, sit amet volutpat justo lectus nec risus.} {:type folder, :empty false, :name My Music, :children [{:type folder, :empty false, :name Pop, :children [{:type folder, :empty false, :name Rock, :children [{:type folder, :empty true, :name Empty Folder, :children [{:type yes}]} {:type file, :name Lyrics, :extension .txt, :preview Curabitur molestie ex ligula, ac tincidunt nisi tempor sit amet. Nullam eget varius purus, nec lobortis urna. Pellentesque consequat est fringilla, mollis turpis at, consequat est. In sit amet lectus dui. Vestibulum sodales ligula at diam lacinia iaculis. Cras molestie dui at odio vestibulum feugiat.}]} {:type file, :name Song Lyrics, :extension .txt, :preview Nam venenatis nunc eget imperdiet laoreet. Vivamus luctus luctus neque in luctus. Donec convallis, elit non lobortis molestie, felis tellus molestie nunc, vel condimentum ante enim sit amet augue.}]} {:type file, :name Album Artwork, :extension .png, :preview photos.google.com/abc.jpg} {:type folder, :empty false, :name Acoustic, :children [{:type folder, :empty false, :name Guitar Music, :children [{:type file, :name Fav song lyrics, :extension .txt, :preview Mauris pharetra suscipit purus et molestie. Cras rhoncus est enim, pulvinar tristique orci sagittis non. Sed volutpat tellus id elit laoreet faucibus a quis eros. Sed cursus fermentum ultrices. Praesent blandit luctus feugiat. Nunc est massa, volutpat sed justo sagittis, ultricies pellentesque enim. Mauris lacinia enim ac erat sodales, in feugiat nulla auctor.}]} {:type file, :name song artwork, :extension .png, :preview photos.google.com/abc.jpg}]} {:type file, :name reminder, :extension .txt, :preview Aenean orci dui, dictum at odio sed, malesuada placerat erat. Aliquam eget risus nec lorem convallis commodo. Praesent tincidunt a ligula sed fringilla. Maecenas posuere sem a scelerisque auctor. Nam ultrices maximus elit, quis efficitur nunc auctor ac.}]} {:type file, :name Recipe, :extension .txt, :preview Aliquam bibendum lacus ex, at malesuada purus maximus eget. Mauris viverra diam vel turpis imperdiet dictum. Nam vel augue non diam egestas pulvinar nec nec odio. Nulla tincidunt interdum lorem, vitae tincidunt massa elementum vitae. Nam varius vitae nisl a ullamcorper. Integer dui mauris, vulputate ac sem ac, varius dapibus erat. Ut pharetra ultrices velit, mattis elementum velit varius in. Donec varius turpis purus, sit amet ultricies ipsum elementum nec.}]} {:depth 0, {:type file, :name My Text 1, :extension .txt, :preview In ipsum est, faucibus ac tempor vel, tincidunt ac leo. Vestibulum quis odio nisl. Nulla auctor erat a sem ullamcorper vulputate. Fusce efficitur tempus nulla, eget suscipit tortor imperdiet nec. Aenean finibus, ipsum ut pulvinar euismod, neque tellus vestibulum justo, sit amet volutpat justo lectus nec risus.} {:type folder, :empty false, :name My Music, :children [{:type folder, :empty false, :name Pop, :children [{:type folder, :empty false, :name Rock, :children [{:type folder, :empty true, :name Empty Folder, :children [{:type yes}]} {:type file, :name Lyrics, :extension .txt, :preview Curabitur molestie ex ligula, ac tincidunt nisi tempor sit amet. Nullam eget varius purus, nec lobortis urna. Pellentesque consequat est fringilla, mollis turpis at, consequat est. In sit amet lectus dui. Vestibulum sodales ligula at diam lacinia iaculis. Cras molestie dui at odio vestibulum feugiat.}]} {:type file, :name Song Lyrics, :extension .txt, :preview Nam venenatis nunc eget imperdiet laoreet. Vivamus luctus luctus neque in luctus. Donec convallis, elit non lobortis molestie, felis tellus molestie nunc, vel condimentum ante enim sit amet augue.}]} {:type file, :name Album Artwork, :extension .png, :preview photos.google.com/abc.jpg} {:type folder, :empty false, :name Acoustic, :children [{:type folder, :empty false, :name Guitar Music, :children [{:type file, :name Fav song lyrics, :extension .txt, :preview Mauris pharetra suscipit purus et molestie. Cras rhoncus est enim, pulvinar tristique orci sagittis non. Sed volutpat tellus id elit laoreet faucibus a quis eros. Sed cursus fermentum ultrices. Praesent blandit luctus feugiat. Nunc est massa, volutpat sed justo sagittis, ultricies pellentesque enim. Mauris lacinia enim ac erat sodales, in feugiat nulla auctor.}]} {:type file, :name song artwork, :extension .png, :preview photos.google.com/abc.jpg}]} {:type file, :name reminder, :extension .txt, :preview Aenean orci dui, dictum at odio sed, malesuada placerat erat. Aliquam eget risus nec lorem convallis commodo. Praesent tincidunt a ligula sed
这就是我要在 Javascript 中实现的目标:
const traverseTree = (nodes, depth = 0) => {
nodes.forEach(node => {
updateNodes({...node, depth})
if (node.type === 'folder') {
traverseTree(node.children, depth + 1)
}
})
}
traverseTree(fileTree.root)
};
更新
我最终确实通过使用 doseq
来完成这项工作,就像下面的答案一样。但是,我不得不使用 run!
摆脱该功能,并按照建议跳过下面的 error 2
修复:
(defn dispatch-nodes-to-state [nodes & {:keys [depth] :or {depth 0}}]
(doseq [node nodes]
(if (= (node :type) "folder")
(do
(re-frame/dispatch [:set-nodes (conj {:depth depth} node)])
(dispatch-nodes-to-state (node :children) :depth (inc depth)))
(do
(re-frame/dispatch [:set-nodes (conj {:depth depth} node)])
(dispatch-nodes-to-state (node :children) :depth (inc depth))))))
(defn get-file-tree []
(go (let [file-tree (<! (http/get API-URL request-opts))]
(dispatch-nodes-to-state (get-in file-tree [:body :root])))))
您只需要 dispatch…
函数中的单个节点,但您在初始调用(也许不知道 run!
实际做什么)和recur
。你需要分支,e。 G。通过使用 mapv
或 doseq
而不是 recur
而是实际的递归调用。
此外,您将深度作为关键字参数放在 lambda 列表中,但在 recur
中使用深度作为位置参数调用它。
编辑:我的意思是:
(defn dispatch-nodes-to-state [node & {:keys [depth] :or {depth 0}}]
(re-frame/dispatch [:set-nodes (conj {:depth depth} node)])
(if (= (node :type) "folder") ; <-- Here is error #1
(do
(println "It's a folder")
(recur (node :children) (inc depth))) ; <-- Here is error #2
(println "it's a file")))
错误 #1 是在 (node :type)
中,node
是矢量,而不是地图。这意味着您将矢量而不是地图传递给此函数。
错误 #2 是在 recur
形式中,您再次传递了一个向量,并且您给出的深度不是作为关键字参数,而是作为第二个位置参数。
有两种可能的补救措施:要么接受节点向量,要么只传递单个节点。
接受节点向量在我看来最简单,假设其他部分没问题:
(defn dispatch-nodes-to-state [nodes & {:keys [depth] :or {depth 0}}]
(doseq [node nodes]
(re-frame/dispatch [:set-nodes (conj {:depth depth} node)])
(if (= (node :type) "folder")
(do
(println "It's a folder")
(dispatch-nodes-to-state (node :children) :depth (inc depth)))
(println "it's a file"))))
如果没有你重新设计的细节,我会这样做:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require
[clojure.walk :as walk]
[tupelo.string :as ts]))
我添加了 2 个版本的数据
(def data-1
{:depth 0, :type "folder", :empty false, :name "My Documents",
:children [{:type "file", :name "My Text" 1, :extension ".txt, :preview" " In ipsum est, faucibus ac"}
{:type "folder", :empty false, :name "My Music",
:children [{:type "folder", :empty false, :name "Pop",
:children [{:type "folder", :empty false, :name "Rock",
:children [{:type "folder", :empty true, :name "Empty Folder", :children [{:type "yes"}]}
{:type "file", :name "Lyrics", :extension ".txt", :preview "Curabitur molestie ex ligula, ac tincidunt nisi"}]}
{:type "file", :name "Song Lyrics", :extension ".txt", :preview "Nam venenatis nunc eget imperdiet laoreet. Vivamus"}]}
{:type "file", :name "Album Artwork", :extension ".png", :preview "photos.google.com/abc.jpg"}]}
{:type "file", :name "Recipe", :extension ".txt", :preview " Aliquam bibendum lacus ex",}]})
和第二个版本
(def data-2
{:type "folder",
:empty "false",
:name "My Documents",
:children [{:type "file",
:name "My Text 1",
:extension ".txt",
:preview "In ipsum est, faucibus ac tempor vel, tincidunt ac leo. Vestibulum quis odio nisl. Nulla auctor erat a "}
{:type "folder",
:empty "false",
:name "My Music",
:children [{:type "folder",
:empty "false",
:name "Pop",
:children [{:type "folder",
:empty "false",
:name "Rock",
:children [{:type "folder",
:empty "true",
:name "Empty Folder",
:children []}
{:type "file",
:name "Lyrics",
:extension ".txt",
:preview "Curabitur molestie ex ligula, ac tincidunt nisi tempor sit amet. Nullam eget varius at."}]}
{:type "file",
:name "Song Lyrics",
:extension ".txt",
:preview "Nam venenatis nunc eget imperdiet laoreet. Vivamus luctus luctus neque "}]}]}]})
使用prewalk
打印名称和深度的基本代码
(defn print-name-depth
[node]
(with-result node ; don't change node
(if (map? node)
(let [name (:name node)
depth (:depth node)]
(spyx [name depth])))))
如何递归地增加每个节点及其子节点的深度
(defn add-depth-to-node
[depth node]
(glue node {:depth depth ; add/overwrite dept for current node
:children (let [depth-kids (inc depth)] ; new depth for child nodes
(forv [child (:children node)]
(add-depth-to-node depth-kids child)))}))
并且 运行 整个测试文件(w/o 实际测试,只是打印)
(dotest
(newline)
(let [data-1b (spyx-pretty (add-depth-to-node 0 data-1))
>> (newline)
data-2b (spyx-pretty (add-depth-to-node 0 data-2))]
(newline)
(walk/prewalk print-name-depth data-1b)
(newline)
(walk/prewalk print-name-depth data-2b)))
结果:
-----------------------------------
Clojure 1.10.1 Java 12.0.1
-----------------------------------
Testing tst.demo.core
(add-depth-to-node 0 data-1) =>
{:depth 0,
:type "folder",
:empty false,
:name "My Documents",
:children
[{:type "file",
:name "My Text",
1 :extension,
".txt, :preview" " In ipsum est, faucibus ac",
:depth 1,
:children []}
{:type "folder",
:empty false,
:name "My Music",
:children
[{:type "folder",
:empty false,
:name "Pop",
:children
[{:type "folder",
:empty false,
:name "Rock",
:children
[{:type "folder",
:empty true,
:name "Empty Folder",
:children [{:type "yes", :depth 5, :children []}],
:depth 4}
{:type "file",
:name "Lyrics",
:extension ".txt",
:preview "Curabitur molestie ex ligula, ac tincidunt nisi",
:depth 4,
:children []}],
:depth 3}
{:type "file",
:name "Song Lyrics",
:extension ".txt",
:preview "Nam venenatis nunc eget imperdiet laoreet. Vivamus",
:depth 3,
:children []}],
:depth 2}
{:type "file",
:name "Album Artwork",
:extension ".png",
:preview "photos.google.com/abc.jpg",
:depth 2,
:children []}],
:depth 1}
{:type "file",
:name "Recipe",
:extension ".txt",
:preview " Aliquam bibendum lacus ex",
:depth 1,
:children []}]}
第二组数据:
(add-depth-to-node 0 data-2) =>
{:type "folder",
:empty "false",
:name "My Documents",
:children
[{:type "file",
:name "My Text 1",
:extension ".txt",
:preview
"In ipsum est, faucibus ac tempor vel, tincidunt ac leo. Vestibulum quis odio nisl. Nulla auctor erat a ",
:depth 1,
:children []}
{:type "folder",
:empty "false",
:name "My Music",
:children
[{:type "folder",
:empty "false",
:name "Pop",
:children
[{:type "folder",
:empty "false",
:name "Rock",
:children
[{:type "folder",
:empty "true",
:name "Empty Folder",
:children [],
:depth 4}
{:type "file",
:name "Lyrics",
:extension ".txt",
:preview
"Curabitur molestie ex ligula, ac tincidunt nisi tempor sit amet. Nullam eget varius at.",
:depth 4,
:children []}],
:depth 3}
{:type "file",
:name "Song Lyrics",
:extension ".txt",
:preview
"Nam venenatis nunc eget imperdiet laoreet. Vivamus luctus luctus neque ",
:depth 3,
:children []}],
:depth 2}],
:depth 1}],
:depth 0}
为两个数据集打印 [name depth]
:
[name depth] => ["My Documents" 0]
[name depth] => ["My Text" 1]
[name depth] => ["My Music" 1]
[name depth] => ["Pop" 2]
[name depth] => ["Rock" 3]
[name depth] => ["Empty Folder" 4]
[name depth] => [nil 5]
[name depth] => ["Lyrics" 4]
[name depth] => ["Song Lyrics" 3]
[name depth] => ["Album Artwork" 2]
[name depth] => ["Recipe" 1]
[name depth] => ["My Documents" 0]
[name depth] => ["My Text 1" 1]
[name depth] => ["My Music" 1]
[name depth] => ["Pop" 2]
[name depth] => ["Rock" 3]
[name depth] => ["Empty Folder" 4]
[name depth] => ["Lyrics" 4]
[name depth] => ["Song Lyrics" 3]
我正在尝试递归调用参数为 node :type
folder
的函数,使用 if
语句有条件地过滤掉它们。但是我收到错误:
Uncaught Error: No item :type in vector of length 3
我认为这可能是因为 :children
向量为空,但即使其中有 :type
属性,我仍然会收到错误消息。这个错误有点神秘,我看不到没有 :type
关键字的矢量。
这是我的代码:
(defn dispatch-nodes-to-state [node & {:keys [depth] :or {depth 0}}]
(re-frame/dispatch [:set-nodes (conj {:depth depth} node)])
(if (= (node :type) "folder")
(do
(println "It's a folder")
(recur (node :children) (inc depth)))
(println "it's a file")))
(defn traverse-tree [nodes]
(run! dispatch-nodes-to-state nodes))
(defn get-file-tree []
(go (let [file-tree (<! (http/get API-URL request-opts))]
(traverse-tree (get-in file-tree [:body :root])))))
代码有明显错误吗? 这是我正在遍历的数据结构的片段。提前致谢:
[{:depth 0, :type folder, :empty false, :name My Documents, :children [{:type file, :name My Text 1, :extension .txt, :preview In ipsum est, faucibus ac tempor vel, tincidunt ac leo. Vestibulum quis odio nisl. Nulla auctor erat a sem ullamcorper vulputate. Fusce efficitur tempus nulla, eget suscipit tortor imperdiet nec. Aenean finibus, ipsum ut pulvinar euismod, neque tellus vestibulum justo, sit amet volutpat justo lectus nec risus.} {:type folder, :empty false, :name My Music, :children [{:type folder, :empty false, :name Pop, :children [{:type folder, :empty false, :name Rock, :children [{:type folder, :empty true, :name Empty Folder, :children [{:type yes}]} {:type file, :name Lyrics, :extension .txt, :preview Curabitur molestie ex ligula, ac tincidunt nisi tempor sit amet. Nullam eget varius purus, nec lobortis urna. Pellentesque consequat est fringilla, mollis turpis at, consequat est. In sit amet lectus dui. Vestibulum sodales ligula at diam lacinia iaculis. Cras molestie dui at odio vestibulum feugiat.}]} {:type file, :name Song Lyrics, :extension .txt, :preview Nam venenatis nunc eget imperdiet laoreet. Vivamus luctus luctus neque in luctus. Donec convallis, elit non lobortis molestie, felis tellus molestie nunc, vel condimentum ante enim sit amet augue.}]} {:type file, :name Album Artwork, :extension .png, :preview photos.google.com/abc.jpg} {:type folder, :empty false, :name Acoustic, :children [{:type folder, :empty false, :name Guitar Music, :children [{:type file, :name Fav song lyrics, :extension .txt, :preview Mauris pharetra suscipit purus et molestie. Cras rhoncus est enim, pulvinar tristique orci sagittis non. Sed volutpat tellus id elit laoreet faucibus a quis eros. Sed cursus fermentum ultrices. Praesent blandit luctus feugiat. Nunc est massa, volutpat sed justo sagittis, ultricies pellentesque enim. Mauris lacinia enim ac erat sodales, in feugiat nulla auctor.}]} {:type file, :name song artwork, :extension .png, :preview photos.google.com/abc.jpg}]} {:type file, :name reminder, :extension .txt, :preview Aenean orci dui, dictum at odio sed, malesuada placerat erat. Aliquam eget risus nec lorem convallis commodo. Praesent tincidunt a ligula sed fringilla. Maecenas posuere sem a scelerisque auctor. Nam ultrices maximus elit, quis efficitur nunc auctor ac.}]} {:type file, :name Recipe, :extension .txt, :preview Aliquam bibendum lacus ex, at malesuada purus maximus eget. Mauris viverra diam vel turpis imperdiet dictum. Nam vel augue non diam egestas pulvinar nec nec odio. Nulla tincidunt interdum lorem, vitae tincidunt massa elementum vitae. Nam varius vitae nisl a ullamcorper. Integer dui mauris, vulputate ac sem ac, varius dapibus erat. Ut pharetra ultrices velit, mattis elementum velit varius in. Donec varius turpis purus, sit amet ultricies ipsum elementum nec.}]} {:depth 0, {:type file, :name My Text 1, :extension .txt, :preview In ipsum est, faucibus ac tempor vel, tincidunt ac leo. Vestibulum quis odio nisl. Nulla auctor erat a sem ullamcorper vulputate. Fusce efficitur tempus nulla, eget suscipit tortor imperdiet nec. Aenean finibus, ipsum ut pulvinar euismod, neque tellus vestibulum justo, sit amet volutpat justo lectus nec risus.} {:type folder, :empty false, :name My Music, :children [{:type folder, :empty false, :name Pop, :children [{:type folder, :empty false, :name Rock, :children [{:type folder, :empty true, :name Empty Folder, :children [{:type yes}]} {:type file, :name Lyrics, :extension .txt, :preview Curabitur molestie ex ligula, ac tincidunt nisi tempor sit amet. Nullam eget varius purus, nec lobortis urna. Pellentesque consequat est fringilla, mollis turpis at, consequat est. In sit amet lectus dui. Vestibulum sodales ligula at diam lacinia iaculis. Cras molestie dui at odio vestibulum feugiat.}]} {:type file, :name Song Lyrics, :extension .txt, :preview Nam venenatis nunc eget imperdiet laoreet. Vivamus luctus luctus neque in luctus. Donec convallis, elit non lobortis molestie, felis tellus molestie nunc, vel condimentum ante enim sit amet augue.}]} {:type file, :name Album Artwork, :extension .png, :preview photos.google.com/abc.jpg} {:type folder, :empty false, :name Acoustic, :children [{:type folder, :empty false, :name Guitar Music, :children [{:type file, :name Fav song lyrics, :extension .txt, :preview Mauris pharetra suscipit purus et molestie. Cras rhoncus est enim, pulvinar tristique orci sagittis non. Sed volutpat tellus id elit laoreet faucibus a quis eros. Sed cursus fermentum ultrices. Praesent blandit luctus feugiat. Nunc est massa, volutpat sed justo sagittis, ultricies pellentesque enim. Mauris lacinia enim ac erat sodales, in feugiat nulla auctor.}]} {:type file, :name song artwork, :extension .png, :preview photos.google.com/abc.jpg}]} {:type file, :name reminder, :extension .txt, :preview Aenean orci dui, dictum at odio sed, malesuada placerat erat. Aliquam eget risus nec lorem convallis commodo. Praesent tincidunt a ligula sed
这就是我要在 Javascript 中实现的目标:
const traverseTree = (nodes, depth = 0) => {
nodes.forEach(node => {
updateNodes({...node, depth})
if (node.type === 'folder') {
traverseTree(node.children, depth + 1)
}
})
}
traverseTree(fileTree.root)
};
更新
我最终确实通过使用 doseq
来完成这项工作,就像下面的答案一样。但是,我不得不使用 run!
摆脱该功能,并按照建议跳过下面的 error 2
修复:
(defn dispatch-nodes-to-state [nodes & {:keys [depth] :or {depth 0}}]
(doseq [node nodes]
(if (= (node :type) "folder")
(do
(re-frame/dispatch [:set-nodes (conj {:depth depth} node)])
(dispatch-nodes-to-state (node :children) :depth (inc depth)))
(do
(re-frame/dispatch [:set-nodes (conj {:depth depth} node)])
(dispatch-nodes-to-state (node :children) :depth (inc depth))))))
(defn get-file-tree []
(go (let [file-tree (<! (http/get API-URL request-opts))]
(dispatch-nodes-to-state (get-in file-tree [:body :root])))))
您只需要 dispatch…
函数中的单个节点,但您在初始调用(也许不知道 run!
实际做什么)和recur
。你需要分支,e。 G。通过使用 mapv
或 doseq
而不是 recur
而是实际的递归调用。
此外,您将深度作为关键字参数放在 lambda 列表中,但在 recur
中使用深度作为位置参数调用它。
编辑:我的意思是:
(defn dispatch-nodes-to-state [node & {:keys [depth] :or {depth 0}}]
(re-frame/dispatch [:set-nodes (conj {:depth depth} node)])
(if (= (node :type) "folder") ; <-- Here is error #1
(do
(println "It's a folder")
(recur (node :children) (inc depth))) ; <-- Here is error #2
(println "it's a file")))
错误 #1 是在 (node :type)
中,node
是矢量,而不是地图。这意味着您将矢量而不是地图传递给此函数。
错误 #2 是在 recur
形式中,您再次传递了一个向量,并且您给出的深度不是作为关键字参数,而是作为第二个位置参数。
有两种可能的补救措施:要么接受节点向量,要么只传递单个节点。
接受节点向量在我看来最简单,假设其他部分没问题:
(defn dispatch-nodes-to-state [nodes & {:keys [depth] :or {depth 0}}]
(doseq [node nodes]
(re-frame/dispatch [:set-nodes (conj {:depth depth} node)])
(if (= (node :type) "folder")
(do
(println "It's a folder")
(dispatch-nodes-to-state (node :children) :depth (inc depth)))
(println "it's a file"))))
如果没有你重新设计的细节,我会这样做:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require
[clojure.walk :as walk]
[tupelo.string :as ts]))
我添加了 2 个版本的数据
(def data-1
{:depth 0, :type "folder", :empty false, :name "My Documents",
:children [{:type "file", :name "My Text" 1, :extension ".txt, :preview" " In ipsum est, faucibus ac"}
{:type "folder", :empty false, :name "My Music",
:children [{:type "folder", :empty false, :name "Pop",
:children [{:type "folder", :empty false, :name "Rock",
:children [{:type "folder", :empty true, :name "Empty Folder", :children [{:type "yes"}]}
{:type "file", :name "Lyrics", :extension ".txt", :preview "Curabitur molestie ex ligula, ac tincidunt nisi"}]}
{:type "file", :name "Song Lyrics", :extension ".txt", :preview "Nam venenatis nunc eget imperdiet laoreet. Vivamus"}]}
{:type "file", :name "Album Artwork", :extension ".png", :preview "photos.google.com/abc.jpg"}]}
{:type "file", :name "Recipe", :extension ".txt", :preview " Aliquam bibendum lacus ex",}]})
和第二个版本
(def data-2
{:type "folder",
:empty "false",
:name "My Documents",
:children [{:type "file",
:name "My Text 1",
:extension ".txt",
:preview "In ipsum est, faucibus ac tempor vel, tincidunt ac leo. Vestibulum quis odio nisl. Nulla auctor erat a "}
{:type "folder",
:empty "false",
:name "My Music",
:children [{:type "folder",
:empty "false",
:name "Pop",
:children [{:type "folder",
:empty "false",
:name "Rock",
:children [{:type "folder",
:empty "true",
:name "Empty Folder",
:children []}
{:type "file",
:name "Lyrics",
:extension ".txt",
:preview "Curabitur molestie ex ligula, ac tincidunt nisi tempor sit amet. Nullam eget varius at."}]}
{:type "file",
:name "Song Lyrics",
:extension ".txt",
:preview "Nam venenatis nunc eget imperdiet laoreet. Vivamus luctus luctus neque "}]}]}]})
使用prewalk
(defn print-name-depth
[node]
(with-result node ; don't change node
(if (map? node)
(let [name (:name node)
depth (:depth node)]
(spyx [name depth])))))
如何递归地增加每个节点及其子节点的深度
(defn add-depth-to-node
[depth node]
(glue node {:depth depth ; add/overwrite dept for current node
:children (let [depth-kids (inc depth)] ; new depth for child nodes
(forv [child (:children node)]
(add-depth-to-node depth-kids child)))}))
并且 运行 整个测试文件(w/o 实际测试,只是打印)
(dotest
(newline)
(let [data-1b (spyx-pretty (add-depth-to-node 0 data-1))
>> (newline)
data-2b (spyx-pretty (add-depth-to-node 0 data-2))]
(newline)
(walk/prewalk print-name-depth data-1b)
(newline)
(walk/prewalk print-name-depth data-2b)))
结果:
-----------------------------------
Clojure 1.10.1 Java 12.0.1
-----------------------------------
Testing tst.demo.core
(add-depth-to-node 0 data-1) =>
{:depth 0,
:type "folder",
:empty false,
:name "My Documents",
:children
[{:type "file",
:name "My Text",
1 :extension,
".txt, :preview" " In ipsum est, faucibus ac",
:depth 1,
:children []}
{:type "folder",
:empty false,
:name "My Music",
:children
[{:type "folder",
:empty false,
:name "Pop",
:children
[{:type "folder",
:empty false,
:name "Rock",
:children
[{:type "folder",
:empty true,
:name "Empty Folder",
:children [{:type "yes", :depth 5, :children []}],
:depth 4}
{:type "file",
:name "Lyrics",
:extension ".txt",
:preview "Curabitur molestie ex ligula, ac tincidunt nisi",
:depth 4,
:children []}],
:depth 3}
{:type "file",
:name "Song Lyrics",
:extension ".txt",
:preview "Nam venenatis nunc eget imperdiet laoreet. Vivamus",
:depth 3,
:children []}],
:depth 2}
{:type "file",
:name "Album Artwork",
:extension ".png",
:preview "photos.google.com/abc.jpg",
:depth 2,
:children []}],
:depth 1}
{:type "file",
:name "Recipe",
:extension ".txt",
:preview " Aliquam bibendum lacus ex",
:depth 1,
:children []}]}
第二组数据:
(add-depth-to-node 0 data-2) =>
{:type "folder",
:empty "false",
:name "My Documents",
:children
[{:type "file",
:name "My Text 1",
:extension ".txt",
:preview
"In ipsum est, faucibus ac tempor vel, tincidunt ac leo. Vestibulum quis odio nisl. Nulla auctor erat a ",
:depth 1,
:children []}
{:type "folder",
:empty "false",
:name "My Music",
:children
[{:type "folder",
:empty "false",
:name "Pop",
:children
[{:type "folder",
:empty "false",
:name "Rock",
:children
[{:type "folder",
:empty "true",
:name "Empty Folder",
:children [],
:depth 4}
{:type "file",
:name "Lyrics",
:extension ".txt",
:preview
"Curabitur molestie ex ligula, ac tincidunt nisi tempor sit amet. Nullam eget varius at.",
:depth 4,
:children []}],
:depth 3}
{:type "file",
:name "Song Lyrics",
:extension ".txt",
:preview
"Nam venenatis nunc eget imperdiet laoreet. Vivamus luctus luctus neque ",
:depth 3,
:children []}],
:depth 2}],
:depth 1}],
:depth 0}
为两个数据集打印 [name depth]
:
[name depth] => ["My Documents" 0]
[name depth] => ["My Text" 1]
[name depth] => ["My Music" 1]
[name depth] => ["Pop" 2]
[name depth] => ["Rock" 3]
[name depth] => ["Empty Folder" 4]
[name depth] => [nil 5]
[name depth] => ["Lyrics" 4]
[name depth] => ["Song Lyrics" 3]
[name depth] => ["Album Artwork" 2]
[name depth] => ["Recipe" 1]
[name depth] => ["My Documents" 0]
[name depth] => ["My Text 1" 1]
[name depth] => ["My Music" 1]
[name depth] => ["Pop" 2]
[name depth] => ["Rock" 3]
[name depth] => ["Empty Folder" 4]
[name depth] => ["Lyrics" 4]
[name depth] => ["Song Lyrics" 3]