如何从 flatTreeNode 填充树?

how to populate tree from flatTreeNode?

我有 treeFlatNode 数组,我想以树格式构建它。或者我可以直接在 angular.

树中显示这个数组吗
data=[
  {
   expandable: true
   level: 0
   name: "2021-12-31"
   path: null
  },
  {
   expandable: false
   level: 2
   name: "A.txt"
   path: "2021-12-31/B/C/A.txt"
  }
]
required format
tree=[
   name:"2021-12-03",
   children:[
      name:"B",
      children:[{
         name:"C"
         children:[{
             name:"A.txt"
             children:[]
         }]
     }]
   ]
]

我不使用 Angular,但如果您只需要将公寓转换为嵌套:

var data = [
  {
    expandable: true,
    level: 0,
    name: "2021-12-31",
    path: null
  },
  {
    expandable: false,
    level: 2,
    name: "A.txt",
    path: "2021-12-31/B/C/A.txt"
  }
]

var to_nested = function(flat) {
  var nested = []
  var cache = {}
  var l = flat.length
  var cache_assert = function(name) {
    if (cache[name] == null) {
      cache[name] = {
        name: name,
        children: []
      }
    }
  }
  for (var i = 0; i < l; i++) {
    var current_node = flat[i]
    cache_assert(current_node.name)
    if (current_node.path == null) {
      nested.push(cache[current_node.name])
    } else {
      var names = current_node.path.split("/")
      var parent_name = names.shift()
      cache_assert(parent_name)
      names.forEach(function(name) {
        cache_assert(name)
        cache[parent_name].children.push(cache[name])
        parent_name = name
      })
    }
  }
  return nested
}

var a = to_nested(data)

console.log('a: ', a)
console.log('a: ', a[0].children)
console.log('a: ', a[0].children[0].children)

如果你想return持平:

var level = 0
var cache = []; cache[level] = a.slice(0)
var parent = []; parent[level] = null
var index = []; index[level] = 0
while (level >= 0) {
  var node = cache[level][index[level]]
  if (node != null) {

    console.log('node: ', node)

    if (
      node['children'] != null &&
      Object.prototype.toString.call(node['children']) === '[object Array]' &&
      node['children'].length
    ) {
      level++
      index[level] = 0
      parent[level] = Object.assign({}, node)
      delete parent[level]['children']
      cache[level] = node['children'].slice(0)
    } else {
      index[level]++
    }
  } else {
    parent[level] = null
    level--
    index[level]++
  }
}

因此,要将您的数据结构转换为所需的数据结构,您可以使用以下函数(带注释 =)):

transform(data){

  const tree = [];

  for (let node of data) {

    // If there's no path it's a parent node 
    // but add it only if it doesn't exist yet 
    if (node.path === null && tree.every(n => n.name !== node.name)) {
      tree.push({ name: node.name, children: [] });
      continue;
    }

    // Extract name of parent node and other nodes
    const [parentNodeName, ...pathElems]: string[] = node.path.split('/');

    // Look-up for the parent node
    let parentNode = tree.find(t => t.name === parentNodeName);

    // If parent doesn't exist yet, so we create it here
    if (!parentNode) {
      parentNode = { name: parentNodeName, children: [] } 
    }

    let children = parentNode.children;

    // If the level of the node is relevant
    // otherwise simply iterate over all pathElems
    for(let i = 0; i <= node.level; i ++) {

      let child = children.find(c => c.name === pathElems[i]);

      // If the child doesn't exist yet - create it
      if (!child) {
        child = {
          name: pathElems[i],
          children: []
        }
        
        children.push(child);
        children = child.children;
        continue;
      }

      // Child does exist, so use it's children for the next iteration
      children = child.children;
    }

  }

  return tree;
}

并且您可以调用此函数,例如,在 ngOnInit:

ngOnInit() {
   this.tree = this.transform(this.data);
}

您可以使用对象 (map) 将(子)路径映射到最终树中的节点。如果尚不存在,则将其添加到父项的子项中。

由于您的树结构实际上代表了一片森林(可以有多个根),因此我将结果变量命名为 forest 而不是 tree

片段:

function toForest(data) {
    const roots = [];
    const map = {};
    for (const obj of data) {
        let key = "";
        let children = roots;
        for (const name of (obj.path ?? obj.name).split("/")) {
            let child = map[key += "/" + name]; 
            if (!child) children.push(map[key] = child = { name, children: [] });
            ({children} = child);
        }
    }
    return roots;
}

// Example run
let data = [{expandable: true,level: 0,name: "2021-12-31",path: null}, {expandable: false,level: 2,name: "A.txt",path: "2021-12-31/B/C/A.txt"}];
let forest = toForest(data);
console.log(forest);