[英]Tree structure not building as expected
I'm trying to write a function to create a tree from a given starting directory.我正在尝试编写 function 以从给定的起始目录创建树。 In other words, I choose a directory, and then the function maps absolutely everything in that particular directory.
换句话说,我选择一个目录,然后 function 绝对映射该特定目录中的所有内容。 I've never done anything like this before, but I'm close to the expected output.
我以前从未做过这样的事情,但我已经接近预期的 output。 However, I'm not sure where I'm going wrong.
但是,我不确定我要去哪里错了。
> Test Root
> 1a
> 1b
> 2a
> 2b
> 2c
> 1c
> 2a
> 1d
> 2a
> 2b
> testfile.txt
The first level is good to go.第一级好到go。 The second level is almost good to go, but for some reason it's duplicating the
parent
property and creating an additional nested object.第二级对 go 几乎很好,但由于某种原因,它复制了
parent
属性并创建了一个额外的嵌套 object。 It's also always inserting the type
property.它也总是插入
type
属性。 I've tried removing properties in the constructor
, but that output is just as bewildering.我试过删除
constructor
中的属性,但是 output 一样令人困惑。
{
"parent": null,
"path": "C:\\Users\\Anthony\\Desktop\\Test Root",
"name": "Test Root",
"kids": [
{
"parent": {
"parent": "C:\\Users\\Anthony\\Desktop\\Test Root",
"path": "C:\\Users\\Anthony\\Desktop\\Test Root\\1a",
"name": "1a",
"kids": []
},
"type": "fileType"
},
{
"parent": {
"parent": "C:\\Users\\Anthony\\Desktop\\Test Root",
"path": "C:\\Users\\Anthony\\Desktop\\Test Root\\1b",
"name": "1b",
"kids": [
{
"parent": {
"parent": "C:\\Users\\Anthony\\Desktop\\Test Root\\1b",
"path": "C:\\Users\\Anthony\\Desktop\\Test Root\\1b\\2a",
"name": "2a",
"kids": []
},
"type": "fileType"
},
{
"parent": {
"parent": "C:\\Users\\Anthony\\Desktop\\Test Root\\1b",
"path": "C:\\Users\\Anthony\\Desktop\\Test Root\\1b\\2b",
"name": "2b",
"kids": []
},
"type": "fileType"
},
{
"parent": {
"parent": "C:\\Users\\Anthony\\Desktop\\Test Root\\1b",
"path": "C:\\Users\\Anthony\\Desktop\\Test Root\\1b\\2c",
"name": "2c",
"kids": []
},
"type": "fileType"
}
]
},
"type": "fileType"
},
{
"parent": {
"parent": "C:\\Users\\Anthony\\Desktop\\Test Root",
"path": "C:\\Users\\Anthony\\Desktop\\Test Root\\1c",
"name": "1c",
"kids": [
{
"parent": {
"parent": "C:\\Users\\Anthony\\Desktop\\Test Root\\1c",
"path": "C:\\Users\\Anthony\\Desktop\\Test Root\\1c\\2a",
"name": "2a",
"kids": []
},
"type": "fileType"
}
]
},
"type": "fileType"
},
{
"parent": {
"parent": "C:\\Users\\Anthony\\Desktop\\Test Root",
"path": "C:\\Users\\Anthony\\Desktop\\Test Root\\1d",
"name": "1d",
"kids": [
{
"parent": {
"parent": "C:\\Users\\Anthony\\Desktop\\Test Root\\1d",
"path": "C:\\Users\\Anthony\\Desktop\\Test Root\\1d\\2a",
"name": "2a",
"kids": []
},
"type": "fileType"
},
{
"parent": {
"parent": "C:\\Users\\Anthony\\Desktop\\Test Root\\1d",
"path": "C:\\Users\\Anthony\\Desktop\\Test Root\\1d\\2b",
"name": "2b",
"kids": []
},
"type": "fileType"
}
]
},
"type": "fileType"
},
{
"parent": {
"parent": "C:\\Users\\Anthony\\Desktop\\Test Root",
"path": "C:\\Users\\Anthony\\Desktop\\Test Root\\testfile.txt",
"name": "testfile.txt",
"type": "fileType"
},
"type": "fileType"
}
]
}
async function createTree(root){
const
Node = class {
constructor(parent, path, name, fifo){
this.parent = parent
this.path = path
this.name = name
fifo ? this.kids = [] : this.type = 'fileType'
}
addChild(parent, path, name, fifo){
this.kids.push(new Node(parent, path, name, fifo))
}
},
traverse = async function(node, path){
const childPaths = await fsp.readdir(path)
for (const childPath of childPaths){
const
name = childPath,
stats = await fsp.stat(join(path, childPath))
let
fifo
if (stats.isDirectory()) fifo = 1
else if (stats.isFile()) fifo = 0
const
childNode = new Node(path, join(path, childPath), name, fifo)
node.addChild(childNode)
traverse(childNode, join(path, childPath))
}
},
rootName = root.slice(-1) === '\\' ? root.slice(0,1) : root.slice(root.lastIndexOf('\\')+1),
tree = new Node(null, root, rootName, 1)
traverse(tree, root)
setTimeout(function(){
console.log(JSON.stringify(tree, null, 2))
}, 2500)
}
I just realized my asynchronous functions aren't returning anything.我刚刚意识到我的异步函数没有返回任何东西。 I'm going to have to look over all of this tomorrow.
明天我将不得不检查所有这些。
The problem is that you are passing in only the first argument to your addChild
function here.问题是您在这里只将第一个参数传递给您的
addChild
function。
The addChild
function expects 4 arguments to be provided. addChild
function 预计将提供 4 个 arguments。 However:然而:
node.addChild(childNode)
// is approximately equivalent to:
addChild ( Node {...}, undefined, undefined, undefined)
You should be calling the function like this:您应该像这样调用 function:
node.addChild(childNode.path, childNode.path, childNode.name, childNode.fifo)
You're on the right path logically, approaching a nicely recursive solution, but I think the class is a bit overkill and far too object-oriented for a functional problem such as this.从逻辑上讲,您走在正确的道路上,接近了一个很好的递归解决方案,但我认为 class 有点矫枉过正,而且对于诸如此类的功能问题来说过于面向对象。 Here's a quick example of a more functional version which should give you the result you expect:
这是一个功能更强大的版本的快速示例,它应该可以为您提供您期望的结果:
const nodePath = require('path');
const fs = require('fs');
/**
* Supply an `fs` function and it will turn it into a promisified version
* @param {Function} fn The function to promisify. This means you do not
* need the `fsp` library.
*/
function promisify (fn) {
return (...args) => new Promise((resolve, reject) => fn(...args, (err, data) => err ? reject(err) : resolve(data)));
};
// Create promisified versions of `fs.stat` and `fs.readdir`
const stat = promisify(fs.stat);
const readdir = promisify(fs.readdir);
function createDirectory (parent, path, name, kids) {
return { parent, path, name, kids: kids || [] };
};
function createFile (parent, path, name) {
return { parent, path, name, type: 'fileType' };
}
// The main recursive function.
async function createTree (parent, path) {
let stats = await stat(path);
if (stats.isDirectory()) {
const children = await readdir(path);
// Because each recursive call retruns a promise, we want to continue only when
// all of them have resolved. So we use Promise.all for this.
let child_nodes = await Promise.all(
children.map(child => createTree(path, nodePath.join(path, child)))
);
// Create a directory node
return createDirectory(parent, path, nodePath.basename(path), child_nodes);
}
// Create a file node
return createFile(parent, path, nodePath.basename(path));
};
// Startup code, can use your own stuff here.
async function start () {
let tree = await createTree(null, '/home/james/stackoverflow/58706769/Test Root');
console.log(JSON.stringify(tree, null, 2));
}
start();
Running this file in Node, I get the following output:在 Node 中运行这个文件,我得到以下 output:
{
"parent": null,
"path": "/home/james/stackoverflow/58706769/Test Root",
"name": "Test Root",
"kids": [
{
"parent": "/home/james/stackoverflow/58706769/Test Root",
"path": "/home/james/stackoverflow/58706769/Test Root/1a",
"name": "1a",
"kids": []
},
{
"parent": "/home/james/stackoverflow/58706769/Test Root",
"path": "/home/james/stackoverflow/58706769/Test Root/1b",
"name": "1b",
"kids": [
{
"parent": "/home/james/stackoverflow/58706769/Test Root/1b",
"path": "/home/james/stackoverflow/58706769/Test Root/1b/2a",
"name": "2a",
"kids": []
},
{
"parent": "/home/james/stackoverflow/58706769/Test Root/1b",
"path": "/home/james/stackoverflow/58706769/Test Root/1b/2b",
"name": "2b",
"kids": []
},
{
"parent": "/home/james/stackoverflow/58706769/Test Root/1b",
"path": "/home/james/stackoverflow/58706769/Test Root/1b/2c",
"name": "2c",
"kids": []
}
]
},
{
"parent": "/home/james/stackoverflow/58706769/Test Root",
"path": "/home/james/stackoverflow/58706769/Test Root/1c",
"name": "1c",
"kids": [
{
"parent": "/home/james/stackoverflow/58706769/Test Root/1c",
"path": "/home/james/stackoverflow/58706769/Test Root/1c/2a",
"name": "2a",
"kids": []
}
]
},
{
"parent": "/home/james/stackoverflow/58706769/Test Root",
"path": "/home/james/stackoverflow/58706769/Test Root/1d",
"name": "1d",
"kids": [
{
"parent": "/home/james/stackoverflow/58706769/Test Root/1d",
"path": "/home/james/stackoverflow/58706769/Test Root/1d/2a",
"name": "2a",
"kids": []
},
{
"parent": "/home/james/stackoverflow/58706769/Test Root/1d",
"path": "/home/james/stackoverflow/58706769/Test Root/1d/2b",
"name": "2b",
"kids": []
}
]
},
{
"parent": "/home/james/stackoverflow/58706769/Test Root",
"path": "/home/james/stackoverflow/58706769/Test Root/testfile.txt",
"name": "testfile.txt",
"type": "fileType"
}
]
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.