Я новичок в рекурсии, и у меня есть структура 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"
}
]
}
]
}
]
};



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете передать параметр 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;
}