簡體   English   中英

樹結構未按預期構建

[英]Tree structure not building as expected

我正在嘗試編寫 function 以從給定的起始目錄創建樹。 換句話說,我選擇一個目錄,然后 function 絕對映射該特定目錄中的所有內容。 我以前從未做過這樣的事情,但我已經接近預期的 output。 但是,我不確定我要去哪里錯了。

起始目錄

> Test Root
    > 1a
    > 1b
        > 2a
        > 2b
        > 2c
    > 1c
        > 2a
    > 1d
        > 2a
        > 2b
    > testfile.txt

Output

第一級好到go。 第二級對 go 幾乎很好,但由於某種原因,它復制了parent屬性並創建了一個額外的嵌套 object。 它也總是插入type屬性。 我試過刪除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"
    }
  ]
}

Function

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)
}

我剛剛意識到我的異步函數沒有返回任何東西。 明天我將不得不檢查所有這些。

問題是您在這里只將第一個參數傳遞給您的addChild function。

addChild function 預計將提供 4 個 arguments。 然而:

node.addChild(childNode)

// is approximately equivalent to:

addChild ( Node {...}, undefined, undefined, undefined)

您應該像這樣調用 function:

node.addChild(childNode.path, childNode.path, childNode.name, childNode.fifo)

從邏輯上講,您走在正確的道路上,接近了一個很好的遞歸解決方案,但我認為 class 有點矯枉過正,而且對於諸如此類的功能問題來說過於面向對象。 這是一個功能更強大的版本的快速示例,它應該可以為您提供您期望的結果:

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();

在 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM