Reputation: 1461
Given an array of objects like this:
var items = [{
id: 1
}, {
id: 2,
child: {
id: 3
}
}, {
id: 4,
child: {
id: 5,
child: {
id: 6
}
}
}];
I need a method to remove an item at any level. This code does what I want, but is there a better way?
Initially I tried doing it with one recursive function, but couldn't get that to work.
var removed = removeItems(items, 5);
print(removed);
function removeItems(items, id) {
items.forEach(function(item, index, allItems) {
if (item.id === id) {
items.splice(index, 1);
}
if (item.child) {
item = testChild(item, item.child, id);
}
});
return items;
}
function testChild(parent, child, id) {
if (child.id === id) {
delete parent.child
return parent;
} else {
if (child.child) {
return testChild(child, child.child, id);
}
return parent;
}
}
function print(obj) {
document.querySelector('#out').innerHTML += JSON.stringify(obj, null, 2);
}
jsfiddle: https://jsfiddle.net/syvf46uL/12/
Upvotes: 1
Views: 1370
Reputation: 3189
Here is a general purpose remove function that should work as you want.
var items = [{
id: 1
}, {
id: 2,
child: { id: 3 }
}, {
id: 4,
child: {
id: 5,
child: {
id: 6
}
}
}
];
function remove(src, predicate) {
// for Array
if (Array.isArray(src)) {
for (var i=src.length-1; i>-1; i--) {
if (predicate(src[i])) {
src.splice(i, 1);
} else {
remove(src[i], predicate);
}
}
}
// for Object
else {
for (var i in src) {
if (predicate(src[i])) {
delete src[i];
} else {
remove(src[i], predicate);
}
}
}
}
// remove id == 1
remove(items, function(element) {
return element.id && element.id == 1;
});
console.log(JSON.stringify(items));
// remove id == 6
remove(items, function(element) {
return element.id && element.id == 6;
});
console.log(JSON.stringify(items));
One important problem with your code, an all too common mistake, is that you attempted to shrink the array - via the splice
method - while iterating forward. This will cause you to skip an element every time you remove an element.
Think of it this way, you are iterating 0->length
; you remove ith
element; now you previous (i + 1)th
element has become your ith
element; but you are still iterating 0->length
thus causing you to skip the new ith
element and go onto the (i + 1)th
element, which was your previous (i + 2)th
element. This is solved by iterating backwards length->0
; shrinkage of the array doesn't affect your iterator because the shrinkage always occurs from i+1->length
on wards but you are iterating from i->0
.
Upvotes: 2