Reputation: 11
I have an array with infinite levels in each object and want to add an id
field based on the level. For level 1 the ID should be 1, for level two the ID should be 2, etc.
{
"name": "Anything2",
"code": "SS_1",
"levels": [
{
"levelName": "New level",
"levels": [
{
"levelName": "New Level2",
"levels": [
{
"levelName": "New Level2",
{
"levelName": "New Level2",
"levels": [
{
"levelName": "New level"
}
]
}
},
{
"levelName": "New Level2",
},
{
"levelName": "New Level2",
}
]
},
{
"levelName": "New Level2"
},
{
"levelName": "New Level2",
"levels": [
{
"levelName": "New level"
}
]
}
]
}
]
}
I want to convert the above array into below new array. I have tried using a for
loop, but it's not working. I am not getting the expected data.
{
"name": "Anything2",
"code": "SS_1",
"levels": [
{
"level": 1,
"levelName": "New level",
"levels": [
{
"level": 2,
"levelName": "New Level2",
"levels": [
{
"level": 3,
"levelName": "New Level2",
{
"levelName": "New Level2",
"levels": [
{
"level": 4,
"levelName": "New level"
}
]
}
},
{
"level": 3,
"levelName": "New Level2",
},
{
"level": 3,
"levelName": "New Level2",
}
]
},
{
"level": 2,
"levelName": "New Level2"
},
{
"level": 2,
"levelName": "New Level2",
"levels": [
{
"level": 3,
"levelName": "New level"
}
]
}
]
}
]
}
Upvotes: 1
Views: 1332
Reputation:
Here is a simple solution using a stack and a while loop.
var tree = {
children: [{
children: [{
children: []
}, {
children: []
}]
}, {
children: [{
children: []
}]
}]
};
var stack = [
[tree, 0] // `0` is the `i` below
];
var n; while (n = stack.length) {
let [node, i] = stack[n - 1];
if (i < node.children.length) {
stack.push([node.children[i], 0]);
stack[n - 1][1]++; // increment `i`
} else {
stack.pop();
node.depth = n;
}
}
console.log(tree);
Upvotes: 0
Reputation: 4780
Think it works:
const data = {"name": "Anything2","code": "SS_1","levels": [{"levelName": "New level","levels": [{"levelName": "New Level2","levels": [{"levelName": "New Level2","levels": [{"levelName": "New level"}]},{"levelName": "New Level2",},{"levelName": "New Level2",}]},{"levelName": "New Level2"},{"levelName": "New Level2","levels": [{"levelName": "New level"}]}]}]};
const iter = (arr, level) =>
arr.map((obj) =>
Array.isArray(obj.levels)
? { level, ...obj, levels: iter(obj.levels, level + 1) }
: { level, ...obj });
const result = {...data, levels: iter(data.levels, 1) };
console.dir(result, {depth: null})
.as-console-wrapper{min-height: 100%!important; top: 0}
Upvotes: 0
Reputation: 386540
You could take a recursive approach and hand over an incremented level for each level.
addLevels
takes a level variable and returns a nother function which separates levels
from the object. The rest of the object is a new variable.
The inner function returns a new object with a level
property, the old object without levels
and a property levels
which gets the mapping of the nested arrays.
addLevel
features a closure over level
which keeps the value for the nested function.
const
addLevel = (level = 0) => ({ levels = [], ...o }) =>
({ level, ...o, levels: levels.map(addLevel(level + 1)) }),
data = { name: "Anything2", code: "SS_1", levels: [{ levelName: "New level", levels: [{ levelName: "New Level2", levels: [{ levelName: "New Level2" }, { levelName: "New Level2", levels: [{ levelName: "New level" }] }, { levelName: "New Level2" }, { levelName: "New Level2" }] }, { levelName: "New Level2" }, { levelName: "New Level2", levels: [{ levelName: "New level" }] }] }] },
result = addLevel()(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 13070
Here I call the property "depth":
const data = {
"name": "Anything2",
"code": "SS_1",
"levels": [{
"levelName": "New level",
"levels": [{
"levelName": "New Level2",
"levels": [{
"levelName": "New Level2"
},
{
"levelName": "New Level2",
"levels": [{
"levelName": "New level"
}]
},
{
"levelName": "New Level2"
},
{
"levelName": "New Level2"
}
]
},
{
"levelName": "New Level2"
},
{
"levelName": "New Level2",
"levels": [{
"levelName": "New level"
}]
}
]
}]
};
function addleveldepth(arr, depth = 1) {
arr.forEach(obj => {
obj.depth = depth;
if (obj.levels) {
addleveldepth(obj.levels, depth + 1);
}
});
}
addleveldepth(data.levels);
console.log(data);
Upvotes: 0