Reputation: 2124
I have a sample input of strings in the form of - "a.b.c", "a.d.e", etc.
I want to convert the string parts separated by "." to be represented in a tree structure.
So, I wrote the below function to create a nested dictionary object from such an array of input -
function items_to_tree(items) {
var arr = {};
items.forEach(function(item){
var parts = item.split(".");
var last = parts.pop();
var cursor = arr;
parts.forEach(function(part){
if(!cursor[part]) cursor[part] = {};
cursor = cursor[part];
});
cursor[last] = {};
});
return arr;
}
So, for example If I give the below sample input to this function -
var items = ["a.b", "a.c", "b.c", "a.c", "a.c.d", "a.b.d"]
I get {"a":{"b":{"d":{}},"c":{"d":{}}},"b":{"c":{}}}
as expected.
But, I want the output to be in a format similar to this -
[{name: "a", children: [{name: "b", children: [{name: "d", children: []}]}]}, {name: "c", children: [{name: "d", children: []}]}, {name: "b", children: [{name: "c", children: []}]}]
Is there any way the items_to_tree function can be modified to return such output, or can the intermediate output from the items_to_tree [the nested dictionary] be transformed into this tree like javascript object array.
Upvotes: 1
Views: 1436
Reputation: 386570
You could seach in the nested array for a given name and use that object or create a new one.
var items = ["a.b", "a.c", "b.c", "a.c", "a.c.d", "a.b.d"],
result = [];
items.forEach(function (path) {
path.split('.').reduce(function (level, key) {
var temp = level.find(({ name }) => key === name);
if (!temp) {
temp = { name: key, children: [] };
level.push(temp);
}
return temp.children;
}, result);
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 23372
I would write a second function for the final data conversion. Your items_to_tree
is pretty generic and reusable. Converting this tree to the desired format can be done in a few lines:
function tree_to_format(tree) {
return Object
.keys(tree)
.map(k => ({ name: k, children: tree_to_format(tree[k]) }))
};
Now, you can compose the function you need by piping the result of items_to_tree
to tree_to_format
:
function items_to_tree(items) {
var arr = {};
items.forEach(function(item){
var parts = item.split(".");
var last = parts.pop();
var cursor = arr;
parts.forEach(function(part){
if(!cursor[part]) cursor[part] = {};
cursor = cursor[part];
});
cursor[last] = {};
});
return arr;
}
function tree_to_format(tree) {
return Object
.keys(tree)
.map(k => ({ name: k, children: tree_to_format(tree[k]) }))
};
console.log(
tree_to_format(
items_to_tree(["a.b", "a.c", "b.c", "a.c", "a.c.d", "a.b.d"])
)
);
// or even:
const compose = (f, g) => x => f(g(x));
const items_to_format = compose(tree_to_format, items_to_tree);
Upvotes: 1