JavaScript вернуть элемент с родителями дерева
Я хочу сделать функцию, которая принимает массив id и возвращает фильтры на основе дерева, с родителями. К примеру, если в функцию передам [2, 6], то хочу получить(на основе массива filtersWithId, который я объявил в самом низу сниппета, он выводится в консоль):
[
{
item: 'Сегмент',
type: 'checkbox',
id: 1,
children: [
{ item: 'Малый бизнес', type: 'checkbox', id: 2 }
]
},
{
item: 'Продукт или канал',
type: 'checkbox',
id: 4,
children: [
{
item: 'РКО',
type: 'checkbox'
id: 5,
children: [
{ item: 'Ведение счёта', type: 'checkbox', id: 6 },
]
}
]
}
]
Как видно по этому массиву - из массива children нужно удалять те элементы, id которых не переданно
Я в своём коде использовал функцию preOrder, чтобы проходиться по каждой ветке, когда проставлял каждому объекту id.
Я пытаюсь думать как это сделать, но пока ничего не приходит в голову.
function putIdFilters(filters_) {
const filters = filters_.slice();
const map = new Map();
let num = 0;
preOrder(filters);
function preOrder(node) {
if (node == null) {
return;
}
if (node.length === 1) {
node[0].id = ++num;
map.set(node[0].id, node[0]);
return;
}
node.forEach(item => {
item.id = ++num;
map.set(item.id, item);
preOrder(item.children);
});
}
return {
arr: filters,
map: map
};
}
const filters = [{
item: 'Сегмент',
type: 'checkbox',
children: [{
item: 'Малый бизнес',
type: 'checkbox'
},
{
item: 'Средний бизнес',
type: 'checkbox'
},
]
},
{
item: 'Продукт или канал',
type: 'checkbox',
children: [{
item: 'РКО',
children: [{
item: 'Ведение счёта',
type: 'checkbox'
},
{
item: 'Открытие счёта',
type: 'checkbox'
},
{
item: 'Закрытие счёта',
type: 'checkbox'
},
{
item: 'Платежи и переводы',
type: 'checkbox'
},
{
item: 'Кассовые операции',
type: 'checkbox'
}
]
},
{
item: 'Кредиты и гарантии',
type: 'checkbox',
children: [{
item: 'Кредиты в целом',
type: 'checkbox'
},
{
item: 'Экспресс кредитование',
type: 'checkbox'
},
{
item: 'Овердрафт',
type: 'checkbox'
}
]
},
{
item: 'Бизнес-портал',
type: 'checkbox'
},
{
item: 'Офисы',
type: 'checkbox'
},
{
item: 'Банкоматы',
type: 'checkbox'
}
]
},
{
item: 'Тематика',
type: 'checkbox',
children: [{
item: 'Медленное / несвоевременное обслуживание',
type: 'checkbox'
},
{
item: 'Невыгодные условия / тарифы',
type: 'checkbox'
},
{
item: 'Проблемы с информированием',
type: 'checkbox'
},
{
item: 'Блокировки / ограничения',
type: 'checkbox'
}
]
},
{
item: 'Источник',
type: 'checkbox',
children: [{
item: 'Опросы',
type: 'checkbox'
},
{
item: 'Жалобы и претензии',
type: 'checkbox'
},
{
item: 'Блокировки / ограничения',
type: 'checkbox'
}
]
},
{
item: 'Отзывы',
type: 'checkbox',
children: [{
item: 'Негативные',
type: 'checkbox'
},
{
item: 'Оценка',
type: 'slider',
slider: {
from: 0,
to: 10
}
}
]
},
{
item: 'Не отзывы',
type: 'checkbox',
children: [{
item: 'Негативные',
type: 'checkbox'
},
{
item: 'Оценка по не отзывам',
type: 'slider',
slider: {
from: 0,
to: 14
}
}
]
}
];
const filtersWithId = putIdFilters(filters).arr;
console.log(filtersWithId);
Ответы (2 шт):
Если вас правильно понял, список рутовых элементов можно получить с помощью reduce и рекурсии.
const filters = [{
item: 'Сегмент',
type: 'checkbox',
id: 1,
children: [
{
item: 'Малый бизнес',
type: 'checkbox',
id: 2,
},
{
item: 'Средний бизнес',
type: 'checkbox',
id: 3,
},
],
},
{
item: 'Продукт или канал',
type: 'checkbox',
id: 4,
children: [
{
item: 'РКО',
id: 5,
children: [
{
item: 'Ведение счёта',
type: 'checkbox',
id: 6,
},
{
item: 'Открытие счёта',
type: 'checkbox',
id: 7,
},
{
item: 'Закрытие счёта',
type: 'checkbox',
id: 8,
},
{
item: 'Платежи и переводы',
type: 'checkbox',
id: 9,
},
{
item: 'Кассовые операции',
type: 'checkbox',
id: 10,
},
],
},
{
item: 'Кредиты и гарантии',
type: 'checkbox',
id: 11,
children: [
{
item: 'Кредиты в целом',
type: 'checkbox',
id: 12,
},
{
item: 'Экспресс кредитование',
type: 'checkbox',
id: 13,
},
{
item: 'Овердрафт',
type: 'checkbox',
id: 14,
},
],
},
{
item: 'Бизнес-портал',
type: 'checkbox',
id: 15,
},
{
item: 'Офисы',
type: 'checkbox',
id: 16,
},
{
item: 'Банкоматы',
type: 'checkbox',
id: 17,
},
],
},
{
item: 'Отзывы',
type: 'checkbox',
id: 18,
children: [
{
item: 'Негативные',
type: 'checkbox',
id: 19,
},
{
item: 'Оценка',
type: 'slider',
id: 20,
slider: {
from: 0,
to: 10
},
},
],
},
];
function existIds(data, ids) {
return data.reduce((acum, item)=> {
if (ids.includes(item.id)) {
acum.push(item);
return acum;
}
if (!item.children) return acum;
const ch = existIds(item.children, ids);
if (!ch.length) return acum;
const newItem = Object.assign({}, item);
newItem.children = ch;
acum.push(newItem);
return acum;
}, []);
}
console.log(existIds(filters, [10, 20]));
Можно так, если вы не хотите мутировать исходный массив
const filters = [{
item: 'Сегмент',
type: 'checkbox',
children: [{
item: 'Малый бизнес',
type: 'checkbox'
},
{
item: 'Средний бизнес',
type: 'checkbox'
},
]
},
{
item: 'Продукт или канал',
type: 'checkbox',
children: [{
item: 'РКО',
children: [{
item: 'Ведение счёта',
type: 'checkbox'
},
{
item: 'Открытие счёта',
type: 'checkbox'
},
{
item: 'Закрытие счёта',
type: 'checkbox'
},
{
item: 'Платежи и переводы',
type: 'checkbox'
},
{
item: 'Кассовые операции',
type: 'checkbox'
}
]
},
{
item: 'Кредиты и гарантии',
type: 'checkbox',
children: [{
item: 'Кредиты в целом',
type: 'checkbox'
},
{
item: 'Экспресс кредитование',
type: 'checkbox'
},
{
item: 'Овердрафт',
type: 'checkbox'
}
]
},
{
item: 'Бизнес-портал',
type: 'checkbox'
},
{
item: 'Офисы',
type: 'checkbox'
},
{
item: 'Банкоматы',
type: 'checkbox'
}
]
},
{
item: 'Тематика',
type: 'checkbox',
children: [{
item: 'Медленное / несвоевременное обслуживание',
type: 'checkbox'
},
{
item: 'Невыгодные условия / тарифы',
type: 'checkbox'
},
{
item: 'Проблемы с информированием',
type: 'checkbox'
},
{
item: 'Блокировки / ограничения',
type: 'checkbox'
}
]
},
{
item: 'Источник',
type: 'checkbox',
children: [{
item: 'Опросы',
type: 'checkbox'
},
{
item: 'Жалобы и претензии',
type: 'checkbox'
},
{
item: 'Блокировки / ограничения',
type: 'checkbox'
}
]
},
{
item: 'Отзывы',
type: 'checkbox',
children: [{
item: 'Негативные',
type: 'checkbox'
},
{
item: 'Оценка',
type: 'slider',
slider: {
from: 0,
to: 10
}
}
]
},
{
item: 'Не отзывы',
type: 'checkbox',
children: [{
item: 'Негативные',
type: 'checkbox'
},
{
item: 'Оценка по не отзывам',
type: 'slider',
slider: {
from: 0,
to: 14
}
}
]
}
];
const filteringTree = getFilteringTree(filters,[29, 32, 26]);
console.log(filteringTree);
function getFilteringTree(data,filterArr){
const temp = {};
let num = 0;
let parent = null;
let parentsList = [];
preOrder(data);
function preOrder(node) {
if (!node) {return;}
else{
node.map(item => {
++num;
temp[num]={parent, id:num, node:item};
parentsList.push(parent);
parent = temp[num];
preOrder(item.children);
if(parentsList.length>0) parent = parentsList.pop();
else parent=null;
});
}
}
return filterArr.reduce((acc,index)=>{
if(temp[index]){
acc.push(cloneBranch(temp[index]));
}
return acc;
},[]);
function cloneBranch(item){
let _item = item;
let result = {..._item.node,id:_item.id}
delete result.children;
while(_item.parent){
result = {..._item.parent.node,id:_item.parent.id,children:[result]}
_item = _item.parent;
}
return result;
}
}