1

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/

asked May 29, 2017 at 21:59

1 Answer 1

2

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.

answered May 29, 2017 at 22:42
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.