#javascript #reactjs
#javascript #reactjs
Вопрос:
У меня есть массив объектов, каждый объект должен иметь ключ и заголовок, но дочерние элементы необязательны, и они могут быть вложенными, я могу иметь дочерние элементы внутри дочерних элементов много раз. Я хочу удалить некоторый объект по указанному значению ключа (например, ключ 677). Я пробовал с фильтром, но я удаляю только первый уровень. Также пробовал рекурсию, но не уверен, правильно ли я это сделал.
const data = [{
key: '1',
title: 'title 1',
children: [{
key: '098',
title: 'hey',
children: [{
key: '677',
title: 'child'
}]
}]
},
{
key: '123',
title: 'tile 111'
},
{
key: '345',
title: 'something'
}
];
const rem = '677';
const del = (el) => {
if (!el.children) {
return el.key !== rem;
} else {
if (el.key !== rem) {
del(el.children);
return el;
}
}
};
const res = data.filter((el) => {
return del(el);
});
console.log(res);
Комментарии:
1. 1. возникает синтаксическая ошибка с первыми дочерними элементами — дочерние элементы — это массив прямо сейчас. 2. опубликуйте желаемый результат.
2. Ваш верхний уровень
children
— это массив объектов, поэтому добавьте фигурные скобки3. Пробовали ли вы какие-либо рекурсивные решения? Также было бы неплохо, если бы вы опубликовали код фильтра, который работал только на первом уровне.
Ответ №1:
Я предполагаю, что ваше существующее решение похоже
const data = [
{
key: '1',
title: 'title 1',
children: [{
key: '098',
title: 'hey',
children: [{ key: '677', title: 'child'}]
}]
},
{ key: '123', title: 'tile 111' },
{ key: '345', title: 'something' }
];
function removeByKey(arr, removingKey){
return arr.filter( a => a.key !== removingKey);
}
Таким образом, он работает на первом уровне, но не глубоко.
Просто измените его так, чтобы он выполнял задания
function removeByKey(arr, removingKey){
return arr.filter( a => a.key !== removingKey).map( e => {
return { ...e, children: removeByKey(e.children || [], removingKey)}
});
}
Небольшое предупреждение, для свойства children не будет установлено значение [] для каждого элемента, не имеющего дочерних элементов.
Итак, как это работает? Ну, вместо того, чтобы сохранять приемлемые элементы такими, какие они есть, мы создаем копию, используя {...e}
это эквивалентно {key:e.key, title:e.title, children:e.children}
в данном случае.
Мы знаем, как принудительно переопределить дочерние свойства removeByKey(e.children || [], removingKey)
, поэтому мы вызываем метод рекурсивно. Не функция работает глубоко.
Ответ №2:
Я бы использовал рекурсивный подход с findIndex и splice . Использование some
позволит завершить работу кода без прохождения по всему дереву.
const data = [{
key: '1',
title: 'title 1',
children: [{
key: '098',
title: 'hey',
children: [{
key: '677',
title: 'child'
}]
}]
},
{
key: '123',
title: 'tile 111'
},
{
key: '345',
title: 'something'
}
];
const removeKey = (data, key) => {
// look to see if object exists
const index = data.findIndex(x => x.key === key);
if (index > -1) {
data.splice(index, 1); // remove the object
return true
} else {
// loop over the indexes of the array until we find one with the key
return data.some(x => {
if (x.children) {
return removeKey(x.children, key);
} else {
return false;
}
})
}
}
console.log(removeKey(data, '677'))
console.log(JSON.stringify(data));
Ответ №3:
Вы можете использовать простую рекурсию, чтобы добиться цели:
const data = [
{
key: '1',
title: 'title 1',
children: [
{
key: '098',
title: 'hey',
children: [{ key: '677', title: 'child'}]
}
]
},
{ key: '123', title: 'tile 111' },
{ key: '345', title: 'something' }
];
function removeByKey(key, arr) {
// loop through all items of array
for(let i = 0; i < arr.length; i ) {
// if array item has said key, then remove it
if(arr[i].key === key) {
arr.splice(i, 1);
} else if(typeof(arr[i].children) !== "undefined") {
// if object doesn't have desired key but has children, call this function
// on the children array
removeByKey(key, arr[i].children);
}
}
}
removeByKey('098', data);
console.log(data);
Это может быть немного легче понять, чем другой предоставленный ответ.