Javascript 多维数组到单个对象
Javascript multidimentional array to single object
我很难写一个算法。上下文如下:我有一组路径,我想将它们放入单个对象中,例如重建文件树。
这是一个简单的示例:
var paths = [
'/var/log/log.txt',
'/var/log/test.txt',
'/home/toto/someFile.txt',
'/wtf.txt'
];
我希望这个路径数组是一个对象,例如:
var tree = {
var: {
log: ['log.txt', 'test.txt']
},
home: {
toto: ['someFile.txt']
},
wtf.txt: null // I don't know how to handle this case
};
关于如何做这样的事情有什么提示吗?
实际上,我有类似的东西,但它以单一深度级别结束,而不是在根级别处理文件:
function rebuildTree(paths, tree) {
paths.forEach(function (path) {
var splittedPath;
if (path.indexOf("/") > -1) {
splittedPath = path.split('/');
} else {
splittedPath = [path];
}
splittedPath.some(function(item, index) {
if (!tree.hasOwnProperty(item) && index > 0) {
tree[item] = {};
}
if ((parseInt(index) + 1) <= (splittedPath.length - 1)) {
var nextIndex = parseInt(index + 1);
var nextPath = splittedPath.splice(0, index);
tree[item] = rebuildTree(nextPath, tree[item]);
}
});
});
}
我在下面写了一个小辅助函数,应该很容易做到,请查看评论以了解它是如何工作的(请查看您的控制台以获取输出)。
function treeify(paths){
// This will store our tree
var tree = {};
// This will run through all our paths
paths.forEach(function(path){
// This will remove the initial slash
if(path.indexOf('/') === 0) path = path.substring(1);
// Find all the individual files/folders
path = path.split('/');
// If there is only one we'll assume its a file and assign your `null`
if(path.length === 1){
tree[path[0]] = tree[path[0]] || null;
return;
}
// Create a variable that will store the current branch we are in
var branch = tree[path[0]] = tree[path[0]] || {};
// Loop through the remaining values, repointing the branch as we go.
for(var i = 1; i < path.length; i++){
// The second to last item will need to be an array (as suggested).
if(i === path.length-2)
branch = branch[path[i]] = branch[path[i]] || [];
// The last item will be pushed to the array (as suggested).
else if(i === path.length-1)
branch.push(path[i]);
// All others will simply create a new branch.
else
branch = branch[path[i]] = branch[path[i]] || {};
}
});
return tree;
}
console.log(treeify([
'/var/log/log.txt',
'/var/log/test.txt',
'/home/toto/someFile.txt',
'/wtf.txt'
]));
最大的缺点是它会因为你想要的结构而崩溃。更好的解决方案如下所示,它降低了复杂性并使其更易于理解:
function treeify(paths){
var tree = {};
paths.forEach(function(path){
if(path.indexOf('/') === 0) path = path.substring(1);
path = path.split('/');
var branch = tree[path[0]] = tree[path[0]] || {};
for(var i = 1; i < path.length; i++){
branch = branch[path[i]] = branch[path[i]] || {};
}
});
return tree;
}
console.log(treeify([
'/var/log/log.txt',
'/var/log/test.txt',
'/home/toto/someFile.txt',
'/wtf.txt'
]));
在此代码段中,所有路径都只是嵌套键,您可以使用 for..in
结构来查找内容。它不太方便,但以数组结尾可能会导致以下问题:当您有两条路径时,一条是 a/b/c.txt
,另一条是 a/b/c/d
,推送将中断并且数组将失败。这意味着你只能有一个深度级别,而这个函数可以有任何级别的深度。
我很难写一个算法。上下文如下:我有一组路径,我想将它们放入单个对象中,例如重建文件树。
这是一个简单的示例:
var paths = [
'/var/log/log.txt',
'/var/log/test.txt',
'/home/toto/someFile.txt',
'/wtf.txt'
];
我希望这个路径数组是一个对象,例如:
var tree = {
var: {
log: ['log.txt', 'test.txt']
},
home: {
toto: ['someFile.txt']
},
wtf.txt: null // I don't know how to handle this case
};
关于如何做这样的事情有什么提示吗?
实际上,我有类似的东西,但它以单一深度级别结束,而不是在根级别处理文件:
function rebuildTree(paths, tree) {
paths.forEach(function (path) {
var splittedPath;
if (path.indexOf("/") > -1) {
splittedPath = path.split('/');
} else {
splittedPath = [path];
}
splittedPath.some(function(item, index) {
if (!tree.hasOwnProperty(item) && index > 0) {
tree[item] = {};
}
if ((parseInt(index) + 1) <= (splittedPath.length - 1)) {
var nextIndex = parseInt(index + 1);
var nextPath = splittedPath.splice(0, index);
tree[item] = rebuildTree(nextPath, tree[item]);
}
});
});
}
我在下面写了一个小辅助函数,应该很容易做到,请查看评论以了解它是如何工作的(请查看您的控制台以获取输出)。
function treeify(paths){
// This will store our tree
var tree = {};
// This will run through all our paths
paths.forEach(function(path){
// This will remove the initial slash
if(path.indexOf('/') === 0) path = path.substring(1);
// Find all the individual files/folders
path = path.split('/');
// If there is only one we'll assume its a file and assign your `null`
if(path.length === 1){
tree[path[0]] = tree[path[0]] || null;
return;
}
// Create a variable that will store the current branch we are in
var branch = tree[path[0]] = tree[path[0]] || {};
// Loop through the remaining values, repointing the branch as we go.
for(var i = 1; i < path.length; i++){
// The second to last item will need to be an array (as suggested).
if(i === path.length-2)
branch = branch[path[i]] = branch[path[i]] || [];
// The last item will be pushed to the array (as suggested).
else if(i === path.length-1)
branch.push(path[i]);
// All others will simply create a new branch.
else
branch = branch[path[i]] = branch[path[i]] || {};
}
});
return tree;
}
console.log(treeify([
'/var/log/log.txt',
'/var/log/test.txt',
'/home/toto/someFile.txt',
'/wtf.txt'
]));
最大的缺点是它会因为你想要的结构而崩溃。更好的解决方案如下所示,它降低了复杂性并使其更易于理解:
function treeify(paths){
var tree = {};
paths.forEach(function(path){
if(path.indexOf('/') === 0) path = path.substring(1);
path = path.split('/');
var branch = tree[path[0]] = tree[path[0]] || {};
for(var i = 1; i < path.length; i++){
branch = branch[path[i]] = branch[path[i]] || {};
}
});
return tree;
}
console.log(treeify([
'/var/log/log.txt',
'/var/log/test.txt',
'/home/toto/someFile.txt',
'/wtf.txt'
]));
在此代码段中,所有路径都只是嵌套键,您可以使用 for..in
结构来查找内容。它不太方便,但以数组结尾可能会导致以下问题:当您有两条路径时,一条是 a/b/c.txt
,另一条是 a/b/c/d
,推送将中断并且数组将失败。这意味着你只能有一个深度级别,而这个函数可以有任何级别的深度。