我有一个对象数组,如下所示:
[{ name: 'test',
size: 0,
type: 'directory',
path: '/storage/test' },
{ name: 'asdf',
size: 170,
type: 'directory',
path: '/storage/test/asdf' },
{ name: '2.txt',
size: 0,
type: 'file',
path: '/storage/test/asdf/2.txt' }]
可以有任意数量的任意路径,这是迭代目录中的文件和文件夹的结果。
我要做的是确定这些节点的“根”节点。最终,这将存储在mongodb中并使用物化路径来确定它的关系。
在此示例中,/storage/test
是没有父级的根。 /storage/test/asdf
的父级/storage/test
是/storage/test/asdf/2.txt
的父级。
我的问题是,你将如何迭代这个数组,以确定父母和相关的孩子?任何正确方向的帮助都会很棒!
谢谢
答案 0 :(得分:6)
你可以这样做:
var arr = [] //your array;
var tree = {};
function addnode(obj){
var splitpath = obj.path.replace(/^\/|\/$/g, "").split('/');
var ptr = tree;
for (i=0;i<splitpath.length;i++)
{
node = { name: splitpath[i],
type: 'directory'};
if(i == splitpath.length-1)
{node.size = obj.size;node.type = obj.type;}
ptr[splitpath[i]] = ptr[splitpath[i]]||node;
ptr[splitpath[i]].children=ptr[splitpath[i]].children||{};
ptr=ptr[splitpath[i]].children;
}
}
arr.map(addnode);
console.log(require('util').inspect(tree, {depth:null}));
输出
{ storage:
{ name: 'storage',
type: 'directory',
children:
{ test:
{ name: 'test',
type: 'directory',
size: 0,
children:
{ asdf:
{ name: 'asdf',
type: 'directory',
size: 170,
children: { '2.txt': { name: '2.txt', type: 'file', size: 0, children: {} } } } } } } } }
答案 1 :(得分:2)
假设/
永远不会出现在文件列表中,那么这样的事情应该有效:
function treeify(files) {
var path = require('path')
files = files.reduce(function(tree, f) {
var dir = path.dirname(f.path)
if (tree[dir]) {
tree[dir].children.push(f)
} else {
tree[dir] = { implied: true, children: [f] }
}
if (tree[f.path]) {
f.children = tree[f.path].children
} else {
f.children = []
}
return (tree[f.path] = f), tree
}, {})
return Object.keys(files).reduce(function(tree, f) {
if (files[f].implied) {
return tree.concat(files[f].children)
}
return tree
}, [])
}
它会将你在问题中提到的数组变成这样的东西:
[ { name: 'test',
size: 0,
type: 'directory',
path: '/storage/test',
children:
[ { name: 'asdf',
size: 170,
type: 'directory',
path: '/storage/test/asdf',
children:
[ { name: '2.txt',
size: 0,
type: 'file',
path: '/storage/test/asdf/2.txt',
children: [] } ] } ] } ]
我实际上没有使用任何其他数据源对此进行测试,因此您的milage可能会有所不同,但至少它应该朝着正确的方向推动您。
答案 2 :(得分:0)
基于@ user568109的解决方案,但以数组而不是对象的形式返回结果:
function filesToTreeNodes(arr) {
var tree = {}
function addnode(obj) {
var splitpath = obj.fileName.replace(/^\/|\/$/g, "").split('/');
var ptr = tree;
for (let i = 0; i < splitpath.length; i++) {
let node: any = {
fileName: splitpath[i],
isDirectory: true
};
if (i == splitpath.length - 1) {
node.isDirectory = false
}
ptr[splitpath[i]] = ptr[splitpath[i]] || node;
ptr[splitpath[i]].children = ptr[splitpath[i]].children || {};
ptr = ptr[splitpath[i]].children;
}
}
function objectToArr(node) {
Object.keys(node || {}).map((k) => {
if (node[k].children) {
objectToArr(node[k])
}
})
if (node.children) {
node.children = Object.values(node.children)
node.children.forEach(objectToArr)
}
}
arr.map(addnode);
objectToArr(tree)
return Object.values(tree)
}
这是可以更好地理解输入/输出格式的签名:
export interface TreeNode {
isDirectory: string
children: TreeNode[]
fileName: string
}
export interface File {
fileName: string
}
export type fileToTreeNodeType = (files: File[]) => TreeNode[]
答案 3 :(得分:0)
如果您想从根路径开始,那么这是该任务的最佳模块:
您可以使用多种配置,并且可以获得类似以下的结果:
{
"name": "sample",
"path": "D:/Github/dree/test/sample",
"relativePath": ".",
"type": "directory",
"size": "1.79 MB",
"children": [
{
"name": "backend",
"path": "D:/Github/dree/test/sample/backend",
"relativePath": "backend",
"type": "directory",
"size": "1.79 MB",
"children": [
{
"name": "firebase.json",
"path": "D:/Github/dree/test/sample/backend/firebase.json",
"relativePath": "backend/firebase.json",
"type": "file",
"extension": "json",
"size": "29 B"
},
{
"name": "server",
"path": "D:/Github/dree/test/sample/backend/server",
"relativePath": "backend/server",
"type": "directory",
"size": "1.79 MB",
"children": [
{
"name": "server.ts",
"path": "D:/Github/dree/test/sample/backend/server/server.ts",
"relativePath": "backend/server/server.ts",
"type": "file",
"extension": "ts",
"size": "1.79 MB"
}
]
}
]
}
]
}
甚至可以返回一个字符串,如下所示:
sample
└─> backend
├── firebase.json
├── hello.txt
└─> server
└── server.ts
例如:
const dree = require('dree');
const config = {
normalize: true,
stat: false,
size: true,
followLinks: true,
exclude: [/exclude_me/, /exclude_me_too/ ],
depth: 10,
extensions: [ 'html', 'txt ]
};
const tree = dree.scan('./dir', config);