删除JS嵌套对象数组中任何级别的项目

时间:2017-05-29 21:59:41

标签: javascript

给出一系列像这样的对象:

var items = [{
  id: 1
}, {
  id: 2, 
  child: {
    id: 3
  }
}, {
  id: 4,
  child: {
    id: 5,
    child: {
      id: 6
    }
  }
}];

我需要一种方法来删除任何级别的项目。这段代码做了我想要的,但有更好的方法吗?

最初我尝试使用一个递归函数,但无法使其工作。

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 个答案:

答案 0 :(得分:1)

这是一个通用的删除功能,可以按你的意愿工作。

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));

您的代码的一个重要问题,一个常见的错误,就是您尝试通过splice方法缩小数组 - 同时向前迭代。这将导致您每次删除元素时跳过元素。

以这种方式思考,你正在迭代0->length;你删除ith元素;现在您之前的(i + 1)th元素已成为您的ith元素;但是您仍在迭代0->length,因此会跳过新的ith元素并转到(i + 1)th元素,这是您以前的(i + 2)th元素。这可以通过向后迭代length->0来解决;数组的收缩不会影响迭代器,因为收缩总是从病房i+1->length开始,但是你从i->0迭代。