у меня есть массив:
[
{id: 1, name: 'Parent1'},
{id: 2, name: 'Child1', parent: {id: 1, name: 'Parent1'}},
{id: 3, name: 'Child2', parent: {id: 1, name: 'Parent1'}},
{id: 4, name: 'GrandChild1', parent: {id: 3, name: 'Child2'}},
{id: 5, name: 'GrandChild2', parent: {id: 3, name: 'Child2'}}
]
Мне нужно написать функцию с аргументом id, которая будет возвращать массив, который не включает элемент с id и все его дочерние элементы и дочерние элементы дочерних элементов. Помогите пожалуйста
Я пытаюсь написать рекурсивную функцию, но не могу
@Mulan функция должна фильтровать дочерние элементы дочерних элементов
Пожалуйста, покажите желаемый результат и неудачную попытку.
Кстати, почему бы не взять только идентификатор родителя вместо объекта?
@Barmar, например, если вы вызываете функцию с id = 1, вы должны получить пустой массив. Или, если вы вызываете func с идентификатором 3, вы должны получить массив с двумя объектами (id: 1 и id: 2)
@NinaScholz Хорошая идея, но не в контексте этой проблемы
Я не понимаю, почему вы сохраняете name
дважды: у каждого элемента есть свойство name
, но также свойство parent
является объектом, который также имеет свойство name
. Но у этого объекта нет свойства parent
. то есть значение parent
кажется не самим родительским объектом, а скорее новым объектом, который имеет то же id
, что и родитель. Предположительно, вам нужно выполнить поиск в массиве, чтобы найти соответствующий объект, соответствующий этому идентификатору, чтобы получить соответствующий объект. Может быть целесообразно сначала построить индекс (от идентификатора к объекту) в зависимости от производительности.
@SergeyGrenaderov Это уточнение должно быть в вопросе, а не в комментарии.
function filterByIdAndChildren(id, arr) {
const filteredArray = [];
function filterItems(inputId, array) {
for (const item of array) {
if (item.id !== inputId) {
if (item.parent && item.parent.id === inputId) {
filterItems(item.id, array);
} else {
filteredArray.push(item);
if (item.parent) {
filterItems(inputId, [item.parent]);
}
}
}
}
}
filterItems(id, arr);
return filteredArray;
}
это должно быть работа!
Нет, если вы вызовете его с идентификатором 1, вы получите массив [{id:4, id: 5}], но это неверно
Я починил это. Проверьте это
Как сейчас написано, ваш ответ неясен. Пожалуйста, отредактируйте , чтобы добавить дополнительные сведения, которые помогут другим понять, как это отвечает на заданный вопрос. Вы можете найти больше информации о том, как писать хорошие ответы в справочном центре.
const validArr = item => typeof item.age === 'number' && item.age > 17;
const thisWontWork = arr => {
return arr.filter(item => {
if (item.id) {
// here is the recursive call
return thisWontWork(item.id).length > 0 && validArr(item);
} else return validArr(item);
});
};
log(thisWontWork(name));
Какое это имеет отношение к вопросу? Где ваша функция ищет данный идентификатор?
Вы можете сохранить нежелательных родителей для последующей фильтрации.
Этот подход работает для несортированных элементов.
const
filter = (array, id) => {
const
parents = Object.fromEntries(array.map(({ id, parent = {} }) => [id, parent.id])),
isParent = pid => id === parents[pid] || pid in parents && isParent(parents[pid]);
return array.filter(o => o.id !== id && !isParent(o.id));
},
data = [{ id: 1, name: 'Parent1' }, { id: 2, name: 'Child1', parent: { id: 1, name: 'Parent1' } }, { id: 3, name: 'Child2', parent: { id: 1, name: 'Parent1' } }, { id: 4, name: 'GrandChild1', parent: { id: 3, name: 'Child2' } }, { id: 5, name: 'GrandChild2', parent: { id: 3, name: 'Child2' } }];
console.info(filter(data, 1));
console.info(filter(data, 2));
console.info(filter(data, 3));
console.info(filter(data, 4));
console.info(filter(data, 5));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ваша функция хороша для отсортированных элементов, но в моем родительском массиве может быть средний элемент (
Я бы так подошёл к проблеме
let values = [
{id: 1, name: 'Parent1'},
{id: 2, name: 'Child1', parent: {id: 1, name: 'Parent1'}},
{id: 3, name: 'Child2', parent: {id: 1, name: 'Parent1'}},
{id: 4, name: 'GrandChild1', parent: {id: 3, name: 'Child2'}},
{id: 5, name: 'GrandChild2', parent: {id: 3, name: 'Child2'}},
{id: 6, name: 'GreatGrandChild', parent: {id: 5, name: 'GrandChild2'}},
{id: 11, name: 'Parent2'},
{id: 12, name: 'Child1ToParent2', parent: {id: 11, name: 'Parent2'}},
{id: 13, name: 'Child2ToParent2', parent: {id: 11, name: 'Parent2'}},
{id: 14, name: 'GrandChild1ToParent2', parent: {id: 13, name: 'Child2ToParent2'}},
{id: 15, name: 'GrandChild2ToParent2', parent: {id: 13, name: 'Child2ToParent2'}},
{id: 16, name: 'GreatGrandChildToParent2', parent: {id: 15, name: 'GrandChild2ToParent2'}},
]
function isDescendant(idRoot, node) {
// If no parent, it is one of the roots of the family tree so we return false
if (!node.parent) {
return false;
}
// Else, finds the parent in the list.
const parent = values.find(value => value.id === node.parent.id);
//Checks if it is the right parent.
if (idRoot === parent.id) {
return true;
}
// Is a great children -> continue recursively
return isDescendant(idRoot, parent);
}
let filteredValues = values.filter(x => isDescendant(1, x))
console.info(filteredValues);
function myfilter(id, nodes) { return nodes.filter(n => n.id != id && n.parent?.id != id) }