Как извлечь пути к «включенным» объектам во вложенных массивах объектов

Я новичок в рекурсии, и у меня есть структура JSON с массивами вложенных объектов. Некоторые из этих объектов имеют логическое значение: true. Я пытаюсь понять, как извлечь пути ко всем включенным объектам и их дочерним элементам.

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


    const sourceData = {
      title: "Work",
      tags: [
        {
          title: "Cleaning",
          tags: [
            {
              title: "Floors"
            },
            { title: "Windows", enabled: true },
            { title: "Ceilings", enabled: true }
          ]
        },
        {
          title: "Maintenance",
          tags: [
            {
              title: "Walls",
              enabled: true,
              tags: [
                {
                  title: "Brickwall"
                },
                {
                  title: "Wooden wall"
                }
              ]
            },
            {
              title: "Roof"
            }
          ]
        },
        {
          title: "Gardening"
        }
      ]
    };

    function getEnabledPaths(level, acc) {
      for (const tag of level.tags) {
        if (tag.enabled) {
          return tag.title;
        } else if (tag.hasOwnProperty("tags")) {
          var path = this.getEnabledPaths(tag);
          if (path) acc.push(tag.title + "." + path);
        }
      }
      return acc;
    }

    console.info(getEnabledPaths(sourceData, []));

Я получаю только:

    [
      "Cleaning.Windows",
      "Maintenance.Walls"
    ]

В идеале я бы получил что-то вроде этого:

    [
      'Work.Cleaning.Windows',
      'Work.Cleaning.Ceilings',
      'Work.Maintenance.Walls.Brickwall',
      'Work.Maintenance.Walls.Wooden Wall'
    ]

В идеальном мире (но я пытался несколько дней и вернулся к получению результатов с точечной нотацией):


    {
      title: "Work",
      tags: [
        {
          title: "Cleaning",
          tags: [
            {
              title: "Windows",
              enabled: true
            },
            {
              title: "Ceilings",
              enabled: true
            }
          ]
        },
        {
          title: "Maintenance",
          tags: [
            {
              title: "Walls",
              enabled: true,
              tags: [
                {
                  title: "Brickwall"
                },
                {
                  title: "Wooden wall"
                }
              ]
            }
          ]
        }
      ]
    };

Поведение ключевого слова "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) для оценки ваших знаний,...
2
0
57
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете передать параметр enabled на более низкие уровни рекурсии, если истинное значение найдено на некоторых из верхних уровней и на основе этого добавить путь к результатам или нет.

const data  = {"title":"Work","tags":[{"title":"Cleaning","tags":[{"title":"Floors"},{"title":"Windows","enabled":true},{"title":"Ceilings","enabled":true}]},{"title":"Maintenance","tags":[{"title":"Walls","enabled":true,"tags":[{"title":"Brickwall"},{"title":"Wooden wall"}]},{"title":"Roof"}]},{"title":"Gardening"}]}

function paths(data, prev = '', enabled = false) {
  const result = [];
  prev += (prev ? "." : '') + data.title;
  if (!enabled && data.enabled) enabled = true;

  if (!data.tags) {
    if (enabled) {
      result.push(prev);
    }
  } else {
    data.tags.forEach(el => result.push(...paths(el, prev, enabled)))
  }
  return result;
}

const result = paths(data)
console.info(result)
Ответ принят как подходящий

Ключом к функции рекурсии является: а) работа с дочерними элементами и б) сам элемент.

Вот мой вариант, который, кажется, работает:

const sourceData = {title:"Work",tags:[{title:"Cleaning",tags:[{title:"Floors"},{title:"Windows",enabled:true},{title:"Ceilings",enabled:true}]},{title:"Maintenance",tags:[{title:"Walls",enabled:true,tags:[{title:"Brickwall"},{title:"Woodenwall"}]},{title:"Roof"}]},{title:"Gardening"}]};

function itemFilter(item) {
  // enabled? done with this item
  if (item.enabled) return item;
  // not enabled and no tags? set to null
  if (!item.tags) return null;
  // filter all children, remove null children
  item.tags = item.tags.map(child => itemFilter(child)).filter(child => child);
  return item;
}

console.info(itemFilter(sourceData));
.as-console-wrapper {
  max-height: 100vh !important;
}

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