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/

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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.