У меня есть список (массив объектов), в котором у них могут быть родители или нет.
const categories = [
{ value: 1, text: 'Food', parent_id: null },
{ value: 2, text: 'Services', parent_id: null },
{ value: 3, text: 'Amazon Prime', parent_id: 2 },
{ value: 4, text: 'Netlix', parent_id: 2 },
{ value: 5, text: 'Beauty', parent_id: null },
{ value: 6, text: 'Education', parent_id: null },
{ value: 8, text: 'Academy', parent_id: 6 },
{ value: 9, text: 'Taxes', parent_id: null },
{ value: 10, text: 'Fees', parent_id: 9 },
{ value: 11, text: 'Recreation', parent_id: null },
{ value: 12, text: 'Pub', parent_id: 11 },
{ value: 13, text: 'House', parent_id: null },
{ value: 15, text: 'Illumination', parent_id: 13 },
{ value: 16, text: 'Internet', parent_id: 13 },
{ value: 18, text: 'Pets', parent_id: null },
{ value: 19, text: 'Award', parent_id: null },
{ value: 20, text: 'Gifts', parent_id: null },
{ value: 21, text: 'Salary', parent_id: null },
{ value: 22, text: 'Health', parent_id: null },
{ value: 23, text: 'Doctor', parent_id: 22 },
{ value: 24, text: 'Pharmacy', parent_id: 22 },
{ value: 25, text: 'Transport', parent_id: null },
{ value: 26, text: 'Trip', parent_id: null },
{ value: 27, text: 'NY', parent_id: 27 },
{ value: 28, text: 'Investment', parent_id: 9 },
{ value: 29, text: 'Bakery', parent_id: 1 },
{ value: 30, text: 'Restaurant', parent_id: 1 },
{ value: 31, text: 'Marketplace', parent_id: 1 },
{ value: 32, text: 'Rent', parent_id: 13 },
{ value: 33, text: 'Phone', parent_id: 13 },
{ value: 34, text: 'Reforms', parent_id: 13 },
{ value: 35, text: 'Telecine', parent_id: 2 },
{ value: 36, text: 'Appliances', parent_id: 13 },
{ value: 37, text: 'Disney', parent_id: 2 },
{ value: 38, text: 'Water', parent_id: 13 },
{ value: 39, text: 'Kitchen', parent_id: 35 },
{ value: 40, text: 'Furniture', parent_id: 40 },
{ value: 41, text: 'Construction Materials', parent_id: 40 },
]
export default categories;
Мне нужно преобразовать этот список в дерево, сделав его из сравнения: если у него есть tag_parent_id, и если он равен значению какого-то другого элемента, это дочерний элемент! Результат должен быть таким:
const categories = [
{ value: 1, text: 'Food', parent_id: null, children: [
{ value: 29, text: 'Bakery', parent_id: 1 },
{ value: 30, text: 'Restaurant', parent_id: 1 },
{ value: 31, text: 'Marketplace', parent_id: 1 },
] },
{ value: 2, text: 'Services', parent_id: null, children: [
{ value: 3, text: 'Amazon Prime', parent_id: 2 },
{ value: 4, text: 'Netlix', parent_id: 2 },
{ value: 35, text: 'Telecine', parent_id: 2 },
{ value: 37, text: 'Dinsey', parent_id: 2 },
] },
{ value: 5, text: 'Beauty', parent_id: null },
{ value: 6, text: 'Education', parent_id: null, children: [
{ value: 8, text: 'Academy', parent_id: 6 },
] },
{ value: 9, text: 'Taxes', parent_id: null, children: [
{ value: 28, text: 'Investment', parent_id: 9 },
{ value: 10, text: 'Fees', parent_id: 9 },
] },
{ value: 11, text: 'Recreation', parent_id: null, children: [
{ value: 12, text: 'Pub', parent_id: 11 },
] },
{ value: 13, text: 'House', parent_id: null, children: [
{ value: 15, text: 'Illumination', parent_id: 13 },
{ value: 16, text: 'Internet', parent_id: 13 },
{ value: 32, text: 'Rent', parent_id: 13 },
{ value: 33, text: 'Phone', parent_id: 13 },
{ value: 34, text: 'Reforms', parent_id: 13, children: [
{ value: 39, text: 'Kitchen', parent_id: 36, children: [
{ value: 40, text: 'Furniture', parent_id: 39 },
{ value: 41, text: 'Construction Materials', parent_id: 39 },
] },
] },
{ value: 36, text: 'Appliances', parent_id: 13 },
{ value: 38, text: 'Water', parent_id: 13 },
] },
{ value: 18, text: 'Pets', parent_id: null },
{ value: 19, text: 'Award', parent_id: null },
{ value: 20, text: 'Gifts', parent_id: null },
{ value: 21, text: 'Salary', parent_id: null },
{ value: 22, text: 'Health', parent_id: null, children: [
{ value: 23, text: 'Doctor', parent_id: 22 },
{ value: 24, text: 'Pharmacy', parent_id: 22 },
] },
{ value: 25, text: 'Transport', parent_id: null },
{ value: 26, text: 'Trip', parent_id: null, children: [
{ value: 27, text: 'NY', parent_id: 26},
] },
]
Я создал следующую функцию:
cascateCategories(state) {
var end = [];
getNestedChildren(state.categories)
return end
function getNestedChildren(categories) {
for(let i in categories) {
categories.forEach(category => {
if (category.value == categories[i].parent_id) {
if (!category.children) {
category['children'] = [];
}
category.children.push(categories[i]);
end.push(category)
}
});
console.info(end);
}
return end;
}
},
Однако он добавляет один и тот же элемент несколько раз, а не только 1. Кроме того, он игнорирует элементы, не имеющие дочерних элементов. В конце концов, у меня проблема с кодом, и я не знаю, какой именно.
Я работаю с VueJS, Vuex и JavaScript.



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


Вы можете взять объект для сбора и вернуть все узлы из родительского узла.
const
categories = [{ value: 1, text: 'Food', parent_id: null }, { value: 2, text: 'Services', parent_id: null }, { value: 3, text: 'Amazon Prime', parent_id: 2 }, { value: 4, text: 'Netlix', parent_id: 2 }, { value: 5, text: 'Beauty', parent_id: null }, { value: 6, text: 'Education', parent_id: null }, { value: 8, text: 'Academy', parent_id: 6 }, { value: 9, text: 'Taxes', parent_id: null }, { value: 10, text: 'Fees', parent_id: 9 }, { value: 11, text: 'Recreation', parent_id: null }, { value: 12, text: 'Pub', parent_id: 11 }, { value: 13, text: 'House', parent_id: null }, { value: 15, text: 'Illumination', parent_id: 13 }, { value: 16, text: 'Internet', parent_id: 13 }, { value: 18, text: 'Pets', parent_id: null }, { value: 19, text: 'Award', parent_id: null }, { value: 20, text: 'Gifts', parent_id: null }, { value: 21, text: 'Salary', parent_id: null }, { value: 22, text: 'Health', parent_id: null }, { value: 23, text: 'Doctor', parent_id: 22 }, { value: 24, text: 'Pharmacy', parent_id: 22 }, { value: 25, text: 'Transport', parent_id: null }, { value: 26, text: 'Trip', parent_id: null }, { value: 27, text: 'NY', parent_id: 27 }, { value: 28, text: 'Investment', parent_id: 9 }, { value: 29, text: 'Bakery', parent_id: 1 }, { value: 30, text: 'Restaurant', parent_id: 1 }, { value: 31, text: 'Marketplace', parent_id: 1 }, { value: 32, text: 'Rent', parent_id: 13 }, { value: 33, text: 'Phone', parent_id: 13 }, { value: 34, text: 'Reforms', parent_id: 13 }, { value: 35, text: 'Telecine', parent_id: 2 }, { value: 36, text: 'Appliances', parent_id: 13 }, { value: 37, text: 'Disney', parent_id: 2 }, { value: 38, text: 'Water', parent_id: 13 }, { value: 39, text: 'Kitchen', parent_id: 35 }, { value: 40, text: 'Furniture', parent_id: 40 }, { value: 41, text: 'Construction Materials', parent_id: 40 }],
tree = function (data, root) {
var t = {};
data.forEach(o => {
Object.assign(t[o.value] ??= {}, o);
t[o.parent_id] ??= {};
t[o.parent_id].children ??= [];
t[o.parent_id].children.push(t[o.value]);
});
return t[root].children
}(categories, null);
console.info(tree);.as-console-wrapper { max-height: 100% !important; top: 0; }Добавляйте в результат только категории без родителя, остальные добавляйте в children их родителя:
// ....
cascateCategories(state) {
const res = [];
for (let category of state.categories) {
if (category.parent_id == null) {
res.push(category);
} else {
const parent = _.find(state.categories, { value: parent_id })
if (parent.children == null) parent.children = [];
parent.children.push(category);
}
}
return res;
}
_ - это lodash.
Если у вас import find from 'lodash/find', то _. можно опустить.
Если элемент с value: v всегда имеет индекс v-1, мы можем установить:
const parent = state.categories[parent_id - 1]
вместо
const parent = _.find(state.categories, { value: parent_id })
Эта функция изменит элементы во входном массиве. Он использует тот факт, что в JavaScript переменные хранят ссылки на объекты, а не на значения.
Мне понравилось ваше решение! Спасибо. Не могли бы вы объяснить мне, что происходит в этой строке: const parent = _.find (state.categories, {value: parent_id})
Вы дважды выполняете цикл по одному и тому же массиву, сначала с
forи вложенным сforEach. Это вызывает дубликаты.