Массив рекурсивных фильтров js

у меня есть массив:

[
 {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 и все его дочерние элементы и дочерние элементы дочерних элементов. Помогите пожалуйста

Я пытаюсь написать рекурсивную функцию, но не могу

function myfilter(id, nodes) { return nodes.filter(n => n.id != id && n.parent?.id != id) }
Mulan 09.04.2023 18:51

@Mulan функция должна фильтровать дочерние элементы дочерних элементов

Sergey Grenaderov 09.04.2023 18:56

Пожалуйста, покажите желаемый результат и неудачную попытку.

Barmar 09.04.2023 19:01

Кстати, почему бы не взять только идентификатор родителя вместо объекта?

Nina Scholz 09.04.2023 19:04

@Barmar, например, если вы вызываете функцию с id = 1, вы должны получить пустой массив. Или, если вы вызываете func с идентификатором 3, вы должны получить массив с двумя объектами (id: 1 и id: 2)

Sergey Grenaderov 09.04.2023 19:05

@NinaScholz Хорошая идея, но не в контексте этой проблемы

Sergey Grenaderov 09.04.2023 19:06

Я не понимаю, почему вы сохраняете name дважды: у каждого элемента есть свойство name, но также свойство parent является объектом, который также имеет свойство name. Но у этого объекта нет свойства parent. то есть значение parent кажется не самим родительским объектом, а скорее новым объектом, который имеет то же id, что и родитель. Предположительно, вам нужно выполнить поиск в массиве, чтобы найти соответствующий объект, соответствующий этому идентификатору, чтобы получить соответствующий объект. Может быть целесообразно сначала построить индекс (от идентификатора к объекту) в зависимости от производительности.

Wyck 09.04.2023 20:03

@SergeyGrenaderov Это уточнение должно быть в вопросе, а не в комментарии.

Barmar 09.04.2023 22:09
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
8
95
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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}], но это неверно

Sergey Grenaderov 09.04.2023 19:08

Я починил это. Проверьте это

samduke 09.04.2023 19:09
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));

Какое это имеет отношение к вопросу? Где ваша функция ищет данный идентификатор?

Barmar 09.04.2023 22:10
Ответ принят как подходящий

Вы можете сохранить нежелательных родителей для последующей фильтрации.

Этот подход работает для несортированных элементов.

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

Ваша функция хороша для отсортированных элементов, но в моем родительском массиве может быть средний элемент (

Sergey Grenaderov 09.04.2023 19:51

Я бы так подошёл к проблеме

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

Другие вопросы по теме