This is a different approach, despide all other solutions, starting from the bottom.
The advantage is, whenever a smaller level is reached, the sum is taken and the actual level accumulator is set to zero.
This solution features only one loop and an array count
for the level accumulation.
I made a bigger test with this data (exception of property children
, which is the result of the algorithm).
{ text: 'A', level: 0, children: 0 }, // A
{ text: 'B', level: 0, children: 1 }, // B
{ text: 'C', level: 1, children: 0 }, // C
{ text: 'D', level: 0, children: 3 }, // D
{ text: 'E', level: 1, children: 2 }, // E
{ text: 'F', level: 2, children: 0 }, // F
{ text: 'F', level: 2, children: 0 }, // G
{ text: 'H', level: 0, children: 18 }, // H
{ text: 'I', level: 1, children: 5 }, // I
{ text: 'J', level: 2, children: 1 }, // J
{ text: 'K', level: 3, children: 0 }, // K
{ text: 'L', level: 2, children: 2 }, // L
{ text: 'M', level: 3, children: 1 }, // M
{ text: 'N', level: 4, children: 0 }, // N
{ text: 'O', level: 1, children: 10 }, // O
{ text: 'P', level: 2, children: 9 }, // P
{ text: 'Q', level: 3, children: 7 }, // Q
{ text: 'R', level: 4, children: 5 }, // R
{ text: 'S', level: 5, children: 2 }, // S
{ text: 'T', level: 6, children: 0 }, // T
{ text: 'U', level: 6, children: 0 }, // U
{ text: 'V', level: 5, children: 0 }, // V
{ text: 'W', level: 5, children: 0 }, // W
{ text: 'X', level: 4, children: 0 }, // X
{ text: 'Y', level: 3, children: 0 }, // Y
{ text: 'Z', level: 1, children: 0 }, // Z
var data = [{ text: 'A', level: 0 }, { text: 'B', level: 0 }, { text: 'C', level: 1 }, { text: 'D', level: 0 }, { text: 'E', level: 1 }, { text: 'F', level: 2 }, { text: 'F',level: 2 }, { text: 'H', level: 0 }, { text: 'I', level: 1 }, { text: 'J', level: 2 }, { text: 'K', level: 3 }, { text: 'L', level: 2 }, { text: 'M', level: 3 }, { text:'N', level: 4 }, { text: 'O', level: 1 }, { text: 'P', level: 2 }, { text: 'Q', level: 3 }, { text: 'R', level: 4 }, { text: 'S', level: 5 }, { text: 'T', level: 6 }, {text: 'U', level: 6 }, { text: 'V', level: 5 }, { text: 'W', level: 5 }, { text: 'X', level: 4 }, { text: 'Y', level: 3 }, { text: 'Z', level: 1 }],
i = data.length,
count = [];
while (i--) {
if (data[i].level > 0) {
count[data[i].level - 1] = (count[data[i].level - 1] || 0) + (count[data[i].level] || 0) + 1;
}
data[i].children = count[data[i].level] || 0;
count[data[i].level] = 0;
}
document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');
Version with prefilled array count
(no checks for undefined) and a variable for the level.
var data = [{ text: 'A', level: 0 }, { text: 'B', level: 0 }, { text: 'C', level: 1 }, { text: 'D', level: 0 }, { text: 'E', level: 1 }, { text: 'F', level: 2 }, { text: 'F',level: 2 }, { text: 'H', level: 0 }, { text: 'I', level: 1 }, { text: 'J', level: 2 }, { text: 'K', level: 3 }, { text: 'L', level: 2 }, { text: 'M', level: 3 }, { text:'N', level: 4 }, { text: 'O', level: 1 }, { text: 'P', level: 2 }, { text: 'Q', level: 3 }, { text: 'R', level: 4 }, { text: 'S', level: 5 }, { text: 'T', level: 6 }, {text: 'U', level: 6 }, { text: 'V', level: 5 }, { text: 'W', level: 5 }, { text: 'X', level: 4 }, { text: 'Y', level: 3 }, { text: 'Z', level: 1 }],
i = data.length, l,
count = Array.apply(null, { length: 50 }).map(function () { return 0; });
while (i--) {
l = data[i].level;
if (l) {
count[l - 1] += count[l] + 1;
}
data[i].children = count[l];
count[l] = 0;
}
document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');