从数组中删除对象或嵌套对象

时间:2018-11-23 10:04:31

标签: javascript arrays ecmascript-6

我需要从给定的对象ID删除数组中的对象或嵌套对象。

需要删除的对象可以是数组中的根对象,也可以是其中一个根对象中的嵌套对象(此示例中为变体)。

这是数组结构(根对象和变体对象都有唯一的ID):

[
   { id: 1, title: 'object without variants', variants: [] },
   { id: 2, title: 'object with variants', variants: [{ id: 21, title: 'variant 1' }, { id: 22, title: 'variant 2' }]
]

因此,例如,如果从触发删除功能的click事件传递的对象ID为1,我想删除ID为1的整个根对象,如果从click事件传递的对象为21,我仅想要删除ID为2而不是整个根对象下的ID为21的变体。

这怎么办?

更新 我通过使用以下代码使它正常工作(passedObjectId是要删除的对象的ID):

array = array.filter(object => object.id !== passedObjectId);

for (let object of array) {
   object.variants = object.variants.filter(variant => variant.id !== passedObjectId);
}

如果从对象中删除了最后一个变量,我还需要从数组中删除根对象。

下面的代码有效,但是我可以不必使用3个filter()方法而变得更漂亮吗?

array = array.filter(object => object.id !== passedObjectId);

for (let object of array) {
   // Remove the variant from the root object
   object.variants = object.variants.filter(variant => variant.id !== passedObjectId);

   // Remove the root object, if there's no variants left in it
   if (!object.variants.length) {
      array = array.filter(object => object.id !== passedObjectId);
   }
}

另一个更新

我最终使用了这段代码,如果删除了最后一个变体,它也会删除根对象:

array = array.filter(object => {
   const hasRemovedVariant = object.variants.some(variant => variant.id === passedObjectId);

   if (hasRemovedVariant) {
      object.variants = object.variants.filter(variant => variant.id !== passedObjectId);

      return object.variants.length;
   }

   return object.id !== passedObjectId;
});

6 个答案:

答案 0 :(得分:1)

这是一个有关如何分别删除它们的示例,我让您将它们放在一起。如果您在执行过程中有任何疑问或麻烦,请随时提问。

const original = [{
    id: 1,
    title: 'object without variants',
    variants: [],
  },
  {
    id: 2,
    title: 'object with variants',

    variants: [{
      id: 21,
      title: 'variant 1'
    }, {
      id: 22,
      title: 'variant 2'
    }],
  },
  {
    id: 3,
    title: 'object with one variant',

    variants: [{
      id: 21,
      title: 'variant 1'
    }],
  }
];

// Remove the root id
const rootIdToDelete = 1;

const modifiedRoot = original.filter(x => x.id !== rootIdToDelete);

// Remove the variant id
const variantToDelete = 21;

const modifiedRootAndVariant = modifiedRoot.filter((x) => {
  x.variants = x.variants.filter(x => x.id !== variantToDelete);
  
  // Keep only the roots that have at least 1 variant
  return x.variants.length;
});

console.log(modifiedRootAndVariant);

答案 1 :(得分:0)

您需要遍历数组,并检查每个对象ID是否匹配,是否删除对象;否则遍历对象内的变量,并检查匹配项并删除该对象。

请确保在修改要遍历的数组时反向循环,因此索引会发生变化,并且可能会出现索引超出范围的情况

var myArray = getYourArray();
var idToCheck = 1; // get the id

for(int i=myArray.length;i--){
  if(myArray[i].id == idToCheck){
      myArray.splice(i);
  }
  else{
     if(myArray[i].variants.length>0){
       for(int j=myArray[i].variants.length;j--){
          if(myArray[i].variants[j].id == idToCheck){
             myArray[i].variants.splice(j);
          }
       }
     }
   }
}

答案 2 :(得分:0)

此代码段将删除具有指定ID的所有子级,无论层次结构有多大。

<authentication mode="Windows" />
<sessionState mode="InProc" timeout="20" />

答案 3 :(得分:0)

您需要在一个循环内有一个循环。 您可以使用forEach为例。

var arr = [
           { id: 1, title: 'object without variants', variants: [] },
           { id: 2, title: 'object with variants', variants: [{ id: 21, title: 'variant 1' }, { id: 22, title: 'variant 2' }]}
          ];
   
var idToDelete = 21;

arr.forEach(function(obj,i){

 if (obj.id == idToDelete){
    arr.splice(i,1);
    }

 obj.variants.forEach(function(variants,i){
  if (variants.id == idToDelete){
    obj.variants.splice(i,1);
  }

 })
})
console.log(arr)

答案 4 :(得分:0)

人们已经回答了,但是一些功能,递归和不变的代码呢?

let array = [
  { id: 1, title: 'object without variants', variants: [] },
  { id: 2, title: 'object with variants', variants: [{ id: 21, title: 'variant 1' }, { id: 22, title: 'variant 2' }] }
];

const deleteFromArray = (arr, id) => {
  if (!arr) return

  let res = [];
  arr.forEach((obj) => {
    if (obj.id !== id) {
      res.push({ ...obj, variants: deleteFromArray(obj.variants, id) })
    }
  })

  return res;
}

console.log(JSON.stringify(deleteFromArray(array, 1)));

这样,如果您对已删除对象有一些引用,则会在数组中的所有对象(包括任何嵌套变体)中将其删除。

答案 5 :(得分:0)

您可以使用some方法创建递归函数,以便在首次匹配时退出循环,并且可以使用splice删除元素。

const data = [{ id: 1, title: 'object without variants', variants: [] },{ id: 2, title: 'object with variants', variants: [{ id: 21, title: 'variant 1' }, { id: 22, title: 'variant 2' }]}]

function remove(data, oid) {
  data.some((e, i) => {
    if(oid == e.id) return data.splice(i, 1);
    if(e.variants)  remove(e.variants, oid)
  })
}

remove(data, 21)
console.log(data)