Reputation: 12168
I have a json tree with not determined level, which looks like this:
var nodeset = {
"name" : "FORM",
"attributes" : {
"IDFORM" : "59",
"NOMDOC" : "1",
"VERSFORM" : "1.01",
"DATEREPORT" : "10.10.1988"
},
"nodes" : [{
"name" : "PART1",
"persist" : true,
"nodes" : [{
"name" : "FTYPE",
"persist" : true,
"value" : "1",
"weight" : 1
}, {
"name" : "STARTDATE",
"persist" : true,
"value" : "01.10.2011",
"weight" : 1
}, {
"name" : "ENDDATE",
"persist" : true,
"value" : "31.12.2011",
"weight" : 1
}
],
"value" : "31.12.2011",
"weight" : 3
}, {
"name" : "PART2",
"persist" : true,
"nodes" : [{
"name" : "F203",
"persist" : true,
"value" : 12,
"weight" : 1
}, {
"name" : "F204",
"persist" : true,
"value" : 12,
"weight" : 1
}, {
"name" : "STI059DETAIL",
"persist" : false,
"nodes" : [{
"name" : "F1",
"persist" : false,
"value" : "asd",
"weight" : 1
}, {
"name" : "F2",
"persist" : false,
"value" : "asd",
"weight" : 1
}, {
"name" : "F3",
"persist" : false,
"value" : 0,
"weight" : 0
}, {
"name" : "F4",
"persist" : false,
"value" : 0,
"weight" : 0
}
],
"value" : 0,
"weight" : 2
}, {
"name" : "STI059DETAIL",
"persist" : false,
"nodes" : [{
"name" : "F1",
"persist" : false,
"value" : null,
"weight" : 0
}, {
"name" : "F2",
"persist" : false,
"value" : null,
"weight" : 0
}, {
"name" : "F3",
"persist" : false,
"value" : 0,
"weight" : 0
}, {
"name" : "F4",
"persist" : false,
"value" : 0,
"weight" : 0
}
],
"value" : 0,
"weight" : 0
}, {
"name" : "STI059DETAIL",
"persist" : false,
"nodes" : [{
"name" : "F1",
"persist" : false,
"value" : null,
"weight" : 0
}, {
"name" : "F2",
"persist" : false,
"value" : null,
"weight" : 0
}, {
"name" : "F3",
"persist" : false,
"value" : 0,
"weight" : 0
}, {
"name" : "F4",
"persist" : false,
"value" : 0,
"weight" : 0
}
],
"value" : 0,
"weight" : 0
}
],
"value" : 0,
"weight" : 4
}
],
"weight" : 7
};
My task is to remove all nodes from it where weight
is 0
and where nodes
property exists.
As it is a tree, I've tried to use recursive function like this:
function clean(index, owner){
var node = owner[index],
weight = node.weight;
delete node.weight;
if(typeof node.persist != 'undefined'){
delete node.persist;
}
if(!node.nodes)return;
if(!weight){
owner.splice(index, 1);
}
for(var i = 0; i < node.nodes.length; i++){
clean(i, node.nodes);
}
}
for(var i = 0; i < nodeset.nodes.length; i++){
clean(i, nodeset.nodes);
}
But splice()
somehow, doesn't remove anything from there. I've replaced it with delete owner[index]
, which causes null
values on the place of those nodes (which I do not want to see there :(
).
My questions: Why the splice()
function not working as I expected (not deleting nodes)? Also, am I took a correct approach? If no, then any other suggestions would be appreciated.
Regards.
Test fiddle HERE, if it might help somehow.
Upvotes: 2
Views: 3225
Reputation: 234847
You can use Array.filter
and Array.forEach
to filter out nodes with 0 weight. First, define a predicate:
var keepNode = function(node) {
return !(node.weight == 0 && node.hasOwnProperty("nodes"));
};
Then a function to clean a node of unwanted children and then recurse on the remaining children:
function clean(tree) {
if (tree.nodes) {
tree.nodes = tree.nodes.filter(keepNode);
tree.nodes.forEach(clean);
}
}
Finally, process the entire data structure:
clean(nodeset);
There's almost certainly a more elegant way that recurses as it filters, but this should do the job.
EDIT (because I didn't notice the IE8 tag)
For IE8 (which doesn't support filter
), you have a couple of choices. You can use the ES5 shim package that adds most EcmaScript functions to legacy JS engines. Alternatively, you can use this shim (available further down on the documentation page for filter
linked above):
if (!Array.prototype.filter)
{
Array.prototype.filter = function(fun /*, thisp*/)
{
"use strict";
if (this == null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var res = [];
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in t)
{
var val = t[i]; // in case fun mutates this
if (fun.call(thisp, val, i, t))
res.push(val);
}
}
return res;
};
}
Upvotes: 4