Рекурсивно удалить объект из вложенного массива - PullRequest
0 голосов
/ 07 мая 2020

у меня есть такой массив. Возможно неограниченное количество вложений

const myArray = [
  {
   id: 1, 
   children: [
              { 
                id: 3,
                children: []
              }
             ]
  },
  {
   id: 2, children: []
  }
]

Пожалуйста, помогите мне удалить любой объект по id и вернуть новый массив без него.

Ответы [ 6 ]

2 голосов
/ 07 мая 2020

Использование методов массива и рекурсивной функции:

function fn(arr, id) {
  return arr
    .filter((el) => el.id !== id)
    .map((el) => {
      if (!el.children || !el.children.length) return el;
      el.children = fn(el.children, id);
      return el;
    });
}

const myArray = [
  {
    id: 1,
    children: [
      {
        id: 3,
        children: [],
      },
    ],
  },
  {
    id: 2,
    children: [],
  },
];

console.log(fn(myArray,1))
console.log(fn(myArray,2))
console.log(fn(myArray,3))
2 голосов
/ 07 мая 2020

Вы можете разрушить объект и извлечь id и children из объекта. Затем возьмите новый объект с остальной частью бывшего объекта и сопоставьте дочерние элементы.

const
    withoutId = ({ id, children, ...o }) => ({ ...o, children: children.map(withoutId) }),
    array = [{ id: 1, children: [{ id: 3, children: [] }] }, { id: 2, children: [] }],
    without = array.map(withoutId);

console.log(without);
2 голосов
/ 07 мая 2020
function removeFromArrayOfObj (array, idToRemove) {
  for (const [i, e] of array.entries()) {
    if (e.id === idToRemove) {
     array.splice(i, 1)
     continue
    }
   if (e.children) {
     removeFromArrayOfObj(e.children, idToRemove)
    }
 }
 return array
}
1 голос
/ 07 мая 2020

Для меня имеет смысл отделить рекурсивный обход и фильтрацию от фактических деталей удаления определенного идентификатора. Поэтому я бы написал более общую функцию c filterDeep, которая сохраняет только те объекты, для которых предикат истинен, рекурсивно переходя в children узлы.

Затем мы можем предоставить ему предикат, который проверяет, элемент соответствует указанному c id. Или, скорее, поскольку мы удаляем те, которые совпадают, наш предикат на самом деле проверяет, соответствует ли наш узел идентификатору.

Это реализация этой идеи:

const filterDeep = (pred) => (xs) =>
  xs .flatMap (x => pred (x)
    ? [{... x, children: filterDeep (pred) (x .children || [])}] 
    : []
  )
  
const removeId = (id) =>  
  filterDeep (x => x.id !== id)

const myArray = [{id: 1, children: [{id: 3, children: []}]}, {id: 2, children: []}]

console .log (removeId (1) (myArray))
console .log (removeId (2) (myArray))
console .log (removeId (3) (myArray))
console .log (removeId (42) (myArray))
.as-console-wrapper {min-height: 100% !important; top: 0}

Это будет включать узел children, даже если у оригинала его не было. Если бы мы хотели включить его только в том случае, если он был изначально, мы могли бы изменить его на что-то вроде этого:

const filterDeep = (pred) => (xs) =>
  xs .flatMap (x => pred (x) 
    ? [{
        ... x, 
        ... (x.children ? {children: filterDeep (pred) (x .children || [])} : {})
      }] 
    : []
  )

Или, что немного сложнее, мы могли бы включить только узел children когда он доступен в родительском элементе и результаты непустые. Это оставлено в качестве упражнения для читателя. : -)

1 голос
/ 07 мая 2020

Функция recursiveRemove рекурсивно удалит элементы из массива и вернет новый список.

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

function recursiveRemove ( list, id ) {
    return list.map ( item => { return {...item} }).filter ( item => {
        if ( 'children' in item ) {
            item.children = recursiveRemove ( item.children, id );
        }
        return item.id !== id;
    });
}
const test1 = recursiveRemove ( myArray, 1);
const test2 = recursiveRemove ( myArray, 2);
const test3 = recursiveRemove ( myArray, 3);
0 голосов
/ 07 мая 2020

А, домашние задания.

  • напишите 'kill_entries_with_id (child_array, id_to_kill)'. Для каждого элемента дочернего массива он должен del элемент, если его идентификатор совпадает. В противном случае он должен рекурсивно вызывать себя вместе с дочерними элементами элемента.
  • Обратите внимание, что вы должны перемещаться по массиву в обратном направлении по индексу, чтобы вам не нужно было беспокоиться об удалении элементов, портящих ваш l oop. Рассмотрим list(range(10,-1,-1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...