Вот массив
const arr = [
{name: "Earth", id: 1, parent_id: -1},
{name: "Europe", id: 2, parent_id: 1},
{name: America": id: 3, parent_id: 1},
{name: "Asia", id: 4, parent_id: 1}
];
Мне нужно добавить ключ иерархии к каждому элементу массива, который будет содержать массив.
const arr = [
{name: "Earth", id: 1, parent_id: -1, hierarchy: ["Earth"]},
{name: "Europe", id: 2, parent_id: 1, hierarchy: ["Earth", "Europe"]},
{name: America": id: 3, parent_id: 1, hierarchy: ["Earth", "America"]},
{name: "Asia", id: 4, parent_id: 1, hierarchy: ["Earth", "Asia"]}
];
Я пытаюсь сделать это с помощью lodash find
const parent = _.find(arr, { id: val.parent_id });
if (parent === undefined) {
val.hierarchy = [val.id];
} else {
val.hierarchy = [...parent.hierarchy, val.id];
}
Но я всегда получаю родительский === неопределенный



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


Для этого вам не нужен lodash. Просто соберите предметы в объект и используйте его, чтобы получить путь.
Конечно, вы можете использовать альтернативу Array#forEach lodash или просто циклы for..of.
const arr = [
{name: "Earth", id: 1, parent_id: -1},
{name: "Europe", id: 2, parent_id: 1},
{name: "America", id: 3, parent_id: 1},
{name: "Asia", id: 4, parent_id: 1},
{name: "New York", id: 5, parent_id: 3},
];
const items = {};
arr.forEach(item => items[item.id] = item);
const traverse = item => item ? traverse(items[item.parent_id]).concat(item.name) : [];
arr.forEach(item => item.hierarchy = traverse(item));
arr.forEach(i=>console.info(JSON.stringify(i)));.as-console-wrapper{max-height:100%!important}Вы можете собрать все узлы и их родителей и построить новый массив с иерархиями.
const
getParents = id => id in references.ids
? [...getParents(references.parents[id]), references.ids[id].name]
: [],
data = [{ name: "Earth", id: 1, parent_id: -1 }, { name: "Europe", id: 2, parent_id: 1 }, { name: "America", id: 3, parent_id: 1 }, { name: "Asia", id: 4, parent_id: 1 }],
references = data.reduce((r, o) => {
r.ids[o.id] = o;
r.parents[o.id] = o.parent_id;
return r;
}, { ids: {}, parents: {} }),
result = data.map(o => ({ ...o, hierarchy: getParents(o.id) }));
console.info(result);.as-console-wrapper { max-height: 100% !important; top: 0; }Предполагаю, что для всех объектов lhs.id < rhs.id => lhs.parent_id < rhs.id.
Мы сделаем это двумя способами:
idhierarchy недвижимостьconst arr = [
{name: "Earth", id: 1, parent_id: -1},
{name: "Europe", id: 2, parent_id: 1},
{name: "America", id: 3, parent_id: 1},
{name: "Asia", id: 4, parent_id: 1},
];
// 1. Store a mapping from ID to object for easy access
const mapping = new Map(arr.map(obj => [obj.id, obj]));
// 2. (optional) sort by ID to ensure the precondition
arr.sort((lhs, rhs) => {
if (lhs.id == rhs.id) {
return 0;
}
return lhs.id < rhs.id ? -1 : 1;
});
// 3. Build the hierarchy
arr.forEach(obj => {
if (obj.parent_id < 0) {
obj.hierarchy = [obj.name];
return;
}
if (!mapping.has(obj.parent_id)) {
// This is a possibility, do what you wish here
obj.hierarchy = ["<incomplete>", obj.name];
return;
}
const parent = mapping.get(obj.parent_id);
const parentHierarchy = parent.hierarchy;
obj.hierarchy = [...parentHierarchy, obj.name];
});
console.info(arr);
arr.map(e => { const parent = arr.find(x => x.id === e.parent_id); const hierarchy = []; if (parent) hierarchy.push(parent.name); hierarchy.push(e.name); return {...e, hierarchy}; })