Удалить объект или вложенный объект из массива - PullRequest
0 голосов
/ 23 ноября 2018

Мне нужно удалить объект или вложенный объект в массиве из заданного идентификатора объекта.

Объект, который необходимо удалить, может быть как корневым объектом в массиве, так и вложенным объектом (вариантв этом примере) в одном из корневых объектов.

Вот структура массива (и корневые объекты, и объекты вариантов имеют уникальные идентификаторы):

[
   { 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, которое запускает функцию удаления 1, я хочу удалить весь корневой объект с идентификатором 1, а если объект, переданный из события click, равен 21, я хочу удалить только вариант с идентификатором 21 вкорневой объект с идентификатором 2, а не весь корневой объект.

Как это можно сделать?

ОБНОВЛЕНИЕ Я получил его с помощью этого кода (прошлоObjectIdидентификатор удаляемого объекта):

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 голосов
/ 23 ноября 2018

Вы можете создать рекурсивную функцию с помощью метода 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)
0 голосов
/ 23 ноября 2018

Люди уже ответили, но как насчет функционального, рекурсивного и неизменяемого кода:

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

Таким образом, если у вас есть какая-либо ссылка на удаленный объект, он удаляется во ВСЕХ объектах в вашем массиве, включая любые вложенные варианты.

0 голосов
/ 23 ноября 2018

Вы должны иметь цикл внутри цикла.Вы можете использовать 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)
0 голосов
/ 23 ноября 2018

Этот фрагмент удалит любого дочернего элемента с указанным идентификатором, независимо от размера иерархии.

var myArray = [{
    id: 1,
    title: 'object without variants',
    variants: []
  },
  {
    id: 2,
    title: 'object with variants',
    variants: [{
      id: 21,
      title: 'variant 1',
      variants: [{
        id: 23,
        title: 'variant 1'
      }, {
        id: 24,
        title: 'variant 2'
      }]
    }, {
      id: 22,
      title: 'variant 2'
    }]
  }
]

console.log(deleteByID(myArray, 21));

function deleteByID(array, id) {
  for (var i = 0; i < array.length; i++) {
    var item = array[i];

    deleteItemByID(myArray, item, id, i);
  }

  return array;
}

function deleteItemByID(array, item, id, count) {
  if (item.id == id) {
    array.splice(count, 1);
    return;
  } else {
    if (item.variants) {
      if (typeof item.variants === "object") {
        for (var i = 0; i < item.variants.length; i++) {
          var varItem = item.variants[i];
          deleteItemByID(item.variants, varItem, id, i);
        }
      }
    }
  }
}
0 голосов
/ 23 ноября 2018

Вам нужно перебрать свой массив и проверить, является ли каждый идентификатор объекта совпадением, если это удаление объекта, в противном случае перебрать ваши варианты внутри объекта и проверить совпадение и удалить объект.

Убедитесь, что вы зацикливаетесь в обратном порядке, когда вы изменяете массив, через который вы проходите, следовательно, индексы меняются, и вы можете получить исключение из диапазона индекса

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);
          }
       }
     }
   }
}
0 голосов
/ 23 ноября 2018

Вот пример того, как вы можете удалить их отдельно, я позволю вам собрать это вместе.Если у вас есть какие-либо вопросы или проблемы, связанные с этим, не стесняйтесь спрашивать.

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...