I'm having a hard time writing an algorithm. The context is the following : I'm having an array of paths that I want to put in a single object, like rebuilding a tree of files.
我很难写出一个算法。上下文是这样的:我有一个路径数组,我想把它放在一个对象中,就像重新构建文件树一样。
Here's a simple sample :
这里有一个简单的例子:
var paths = [
'/var/log/log.txt',
'/var/log/test.txt',
'/home/toto/someFile.txt',
'/wtf.txt'
];
And I'd like this array of paths to be an object like :
我希望这个路径数组是这样的对象:
var tree = {
var: {
log: ['log.txt', 'test.txt']
},
home: {
toto: ['someFile.txt']
},
wtf.txt: null // I don't know how to handle this case
};
Any hint on how to do such a thing ?
关于如何做这样的事有什么提示吗?
Actually, I've something like this but it ends up with a single depth level and not handling file on root level :
实际上,我有一些类似的东西,但它以一个单一的深度级别结束,不处理根级别的文件:
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]);
}
});
});
}
1 个解决方案
#1
0
I have written a little helper function below that should make it easy to do, check the comments to see how it works (see your console for the output).
我在下面写了一个小的帮助函数,它应该很容易实现,请检查注释以了解它是如何工作的(关于输出,请参阅控制台)。
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'
]));
The big downside to this is that it breaks because of the structure you want to have. A better solution would be something like the following, which reduces complexity and makes it easier to understand:
它最大的缺点是它会因为你想要的结构而断裂。一个更好的解决方案应该是以下内容,它可以降低复杂性,并使其更易于理解:
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'
]));
In this snippet all paths are just nested keys, and you could use the for..in
construct to find something. It's less convenient, but ending in an array could cause the following issue: when you have two paths, one being a/b/c.txt
and the other being a/b/c/d
, the push will break and the array will fail. This means you can only have one level of depth, while this function can have any level of depths.
在这段代码中,所有路径都是嵌套的键,您可以使用for。在构造中寻找一些东西。这样做不太方便,但是以数组结尾可能会导致以下问题:当有两条路径时,一条是a/b/c。txt和另一个是a/b/c/d, push会中断,数组会失败。这意味着你只能有一个深度,而这个函数可以有任何深度。
#1
0
I have written a little helper function below that should make it easy to do, check the comments to see how it works (see your console for the output).
我在下面写了一个小的帮助函数,它应该很容易实现,请检查注释以了解它是如何工作的(关于输出,请参阅控制台)。
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'
]));
The big downside to this is that it breaks because of the structure you want to have. A better solution would be something like the following, which reduces complexity and makes it easier to understand:
它最大的缺点是它会因为你想要的结构而断裂。一个更好的解决方案应该是以下内容,它可以降低复杂性,并使其更易于理解:
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'
]));
In this snippet all paths are just nested keys, and you could use the for..in
construct to find something. It's less convenient, but ending in an array could cause the following issue: when you have two paths, one being a/b/c.txt
and the other being a/b/c/d
, the push will break and the array will fail. This means you can only have one level of depth, while this function can have any level of depths.
在这段代码中,所有路径都是嵌套的键,您可以使用for。在构造中寻找一些东西。这样做不太方便,但是以数组结尾可能会导致以下问题:当有两条路径时,一条是a/b/c。txt和另一个是a/b/c/d, push会中断,数组会失败。这意味着你只能有一个深度,而这个函数可以有任何深度。