Получить все родительские объекты по значению js
Есть мультивложенный json
let dataset = [
{
"id": 456,
"name": "Name1",
"children": [
{
"id": 3111,
"name": "Name1.1",
"children": [
{
"id": 504,
"name": "Name1.1.1",
"children": [
{
"id": 509,
"name": "Name1.1.1.1",
"children": []
},
]
},
]
},
{
"id": 3120,
"name": "Name1.2",
"children": [
{
"id": 877,
"name": "Name1.2.1",
"children": []
},
]
},
]
},
{
"id": 456,
"name": "Name2",
"children": [
{
"id": 50,
"name": "Name2.1",
"children": []
},
]
},
]
Как получить по значению "id": 509 всех его родителей?
upd сделал такой вариант, но он выводит только самые первые ветки родителей, "id": 877 не выводит.
var current = dataset[0], titles = [];
while(current && current.id != 509){
titles.push(current.name);
current = current.children[0] || {}
}
console.log(titles.join(" > "));
Ответы (3 шт):
Есть очень хорошое решение для таких задач tree-model-js
Очень просто с ним работать:
var TreeModel = require('tree-model'),
tree = new TreeModel();
// ваш dataset конвертировали в дерево
root = tree.parse(dataset);
// теперь у вас доступны много функций для работы с деревом.
// особенно обратите внимание на функцию .walk([options], action, [context])
Сначала, сделал свой рекурсивный обход дерева и вывод родителей. Оно вроде бы работает, но костыльно немного, т.к. для чилдренов после 1го по порядку в ширину уже не будет выводить самый первый корневой узел. (было бы круто, если кто-то доработал этот код)
let currentArr = []
let data = []
function printReverseList(list, id) {
if (list.id !== id){
currentArr.push(list.name)
}
else {
data = currentArr.slice()
}
if (list.children) {
list.children.forEach(element => {
printReverseList(element, id);
}
);
}
currentArr.splice(0)
}
printReverseList(dataset[0], 509); // надо крутить в цикле
console.log(data)
Затем, не стал заморачиваться и последовал совету @id1
Теперь всё отлично работает.
function getAllParentThisNode(dataset, nodeId)
{
let parents = []
var TreeModel = require('tree-model'),
tree = new TreeModel();
dataset.forEach(element => {
let rootMain = tree.parse(element);
rootMain.walk(function (node) {
if (node.model.id === nodeId) {
let x = node.getPath()
x.forEach(element => {
parents.push(element.model.name)
}
)
}
});
})
return parents
}
console.log(getAllParentThisNode(dataset, 877))
Функция, возвращающая массив объектов-родителей, может может выглядеть так:
С использованием tree-model-js:
const getParentsById = (id, data) => {
const TreeModel = require('tree-model'),
tree = new TreeModel(),
root = tree.parse(data);
const path
root.walk(function (node) {
// Halt the traversal by returning false
if (node.model.id === id) {
path= node.getPath()
return false;
}
});
path.pop()
return path.map(item => item.model)
}
Без использования tree-model-js (если data - массив объектов):
const getParentsById = (id, data) => {
const isFoundChild = (id, data, parents) => {
if (data.find(item => item.id == id)) {
return true;
}
else {
for (let item of data) {
if (item.children.length)
if (isFoundChild(id, item.children)) {
parents.push(item);
return true;
}
}
return false;
}
}
const parents = [];
if (data.find(item => item.id == id))
return [];
else {
for (let item of data) {
if (item.children.length)
if (isFoundChild(id, item.children, parents)) {
parents.push(item);
return parents;
}
}
}
}