'Loop tree-like structure (id and parent_id)
I have a tree object generated from the DataBase with my data from Excel
I would like loop this object to get the elements like a tree
For example: I would like to display the data in a table, or do a select depending on another select to select an asset
Or do you think I should change my object structure?¿
Excel
Object (from JSON)
[
{"id":"1000","name":"GRUPOS GENERADORES","parent_id":"0"},
{"id":"1100","name":"MOTORES","parent_id":"1000"},
{"id":"1100.1","name":"MOTOR Nº 1","parent_id":"1100"},
{"id":"1100.2","name":"MOTOR Nº 2","parent_id":"1100"},
{"id":"1100.3","name":"MOTOR Nº 3","parent_id":"1100"},
{"id":"1200","name":"SISTEMAS AUXILIARES MOTOR","parent_id":"1000"},
{"id":"1240","name":"INSTRUMENTACIÓN Y CONTROL","parent_id":"1200"},
{"id":"1242","name":"INSTRUMENTACIÓN","parent_id":"1240"},
{"id":"2000","name":"INSTALACIONES AUXILIARES GRUPOS","parent_id":"0"},
{"id":"2100","name":"REFRIGERACIÓN","parent_id":"2000"},
{"id":"2110","name":"AEROREFRIGERADORES","parent_id":"2100"},
{"id":"2110.1","name":"AEROREFRIGERADOR AR1","parent_id":"2110"},
{"id":"2110.2","name":"AEROREFRIGERADOR AR2","parent_id":"2110"},
{"id":"2110.3","name":"AEROREFRIGERADOR AR3","parent_id":"2110"},
{"id":"2110.4","name":"AEROREFRIGERADOR AR4","parent_id":"2110"},
{"id":"2110.5","name":"AEROREFRIGERADOR AR5","parent_id":"2110"}
{"id":"2160","name":"INSTRUMENTACIÓN","parent_id":"2100"},
{"id":"2160.1","name":"CAUDALÍMETRO AT","parent_id":"2160"},
{"id":"2160.2","name":"CAUDALÍMETRO BT","parent_id":"2160"},
]
I made this method to try to get the child elements from a given name parent, but if i call the method with a name that is duplicated, this method doesn't work.
function filter_by(filter) {
const id = data.filter(i => (i.name === filter))[0].id
const data_filtered = data.filter(i => (i.parent_id === id))
return data_filtered
}
console.log(filter_by("AEROREFRIGERADORES"))
// this throws an error
// console.log(filter_by("INSTRUMENTACIÓN"))
<script>
const data = [
{"id":"1000","name":"GRUPOS GENERADORES","parent_id":"0"},
{"id":"1100","name":"MOTORES","parent_id":"1000"},
{"id":"1100.1","name":"MOTOR Nº 1","parent_id":"1100"},
{"id":"1100.2","name":"MOTOR Nº 2","parent_id":"1100"},
{"id":"1100.3","name":"MOTOR Nº 3","parent_id":"1100"},
{"id":"2000","name":"INSTALACIONES AUXILIARES GRUPOS","parent_id":"0"},
{"id":"2100","name":"REFRIGERACIÓN","parent_id":"2000"},
{"id":"2110","name":"AEROREFRIGERADORES","parent_id":"2100"},
{"id":"2110.1","name":"AEROREFRIGERADOR AR1","parent_id":"2110"},
{"id":"2110.2","name":"AEROREFRIGERADOR AR2","parent_id":"2110"},
{"id":"2110.3","name":"AEROREFRIGERADOR AR3","parent_id":"2110"},
{"id":"2110.4","name":"AEROREFRIGERADOR AR4","parent_id":"2110"},
{"id":"2110.5","name":"AEROREFRIGERADOR AR5","parent_id":"2110"}
];
</script>
Solution 1:[1]
You could get the children first by parent_id and then find the parent item and return the children of this node.
const
find = (data, name) => {
const
children = data.reduce((r, o) => ((r[o.parent_id] ??= []).push(o), r), {});
return children[data.find(o => o.name === name).id];
},
data = [{ id: "1000", name: "GRUPOS GENERADORES", parent_id: "0" }, { id: "1100", name: "MOTORES", parent_id: "1000" }, { id: "1100.1", name: "MOTOR Nº 1", parent_id: "1100" }, { id: "1100.2", name: "MOTOR Nº 2", parent_id: "1100" }, { id: "1100.3", name: "MOTOR Nº 3", parent_id: "1100" }, { id: "2000", name: "INSTALACIONES AUXILIARES GRUPOS", parent_id: "0" }, { id: "2100", name: "REFRIGERACIÓN", parent_id: "2000" }, { id: "2110", name: "AEROREFRIGERADORES", parent_id: "2100" }, { id: "2110.1", name: "AEROREFRIGERADOR AR1", parent_id: "2110" }, { id: "2110.2", name: "AEROREFRIGERADOR AR2", parent_id: "2110" }, { id: "2110.3", name: "AEROREFRIGERADOR AR3", parent_id: "2110" }, { id: "2110.4", name: "AEROREFRIGERADOR AR4", parent_id: "2110" }, { id: "2110.5", name: "AEROREFRIGERADOR AR5", parent_id: "2110" }],
result = find(data, 'AEROREFRIGERADORES');
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Solution 2:[2]
You could:
- Create a nested forest structure from the flat array input
- Create a 2D array from that tree
- Create a HTML table from that 2D array (as example output)
Here are three functions for doing that:
function toForest(data, topLevelParentId="0") {
let children = []; // root(s) of the forest to populate
let map = new Map(data.map(({id, name, parent_id}) => [id, {id, name, children: [] }]))
.set(topLevelParentId, { children }); // Create an entry to hold all the roots
for (let {id, parent_id} of data) map.get(parent_id).children.push(map.get(id));
return children;
}
function toMatrix(forest, depth=0) {
let table = (forest ?? []).flatMap(({id, name, children}) =>
[[id, name], ...toMatrix(children, depth + 1).map(row => ["", ...row])]
);
// Pad rows at the right, so they are all of equal length
let maxWidth = Math.max(...table.map(row => row.length));
return table.map(row => row.concat(
...Array.from({length: maxWidth - row.length}, () => ""))
);
}
function toHTML(matrix) {
return `<table>${matrix.map(row =>
`<tr>${row.map(cell => `<td>${cell}</td>`).join("")}</td>`
).join("\n")}</table>`;
}
// demo
let data = [{"id":"1000","name":"GRUPOS GENERADORES","parent_id":"0"},{"id":"1100","name":"MOTORES","parent_id":"1000"},{"id":"1100.1","name":"MOTOR Nº 1","parent_id":"1100"},{"id":"1100.2","name":"MOTOR Nº 2","parent_id":"1100"},{"id":"1100.3","name":"MOTOR Nº 3","parent_id":"1100"},{"id":"1200","name":"SISTEMAS AUXILIARES MOTOR","parent_id":"1000"},{"id":"1240","name":"INSTRUMENTACIÓN Y CONTROL","parent_id":"1200"},{"id":"1242","name":"INSTRUMENTACIÓN","parent_id":"1240"},{"id":"2000","name":"INSTALACIONES AUXILIARES GRUPOS","parent_id":"0"},{"id":"2100","name":"REFRIGERACIÓN","parent_id":"2000"},{"id":"2110","name":"AEROREFRIGERADORES","parent_id":"2100"},{"id":"2110.1","name":"AEROREFRIGERADOR AR1","parent_id":"2110"},{"id":"2110.2","name":"AEROREFRIGERADOR AR2","parent_id":"2110"},{"id":"2110.3","name":"AEROREFRIGERADOR AR3","parent_id":"2110"},{"id":"2110.4","name":"AEROREFRIGERADOR AR4","parent_id":"2110"},{"id":"2110.5","name":"AEROREFRIGERADOR AR5","parent_id":"2110"},{"id":"2160","name":"INSTRUMENTACIÓN","parent_id":"2100"},{"id":"2160.1","name":"CAUDALÍMETRO AT","parent_id":"2160"},{"id":"2160.2","name":"CAUDALÍMETRO BT","parent_id":"2160"},];
let forest = toForest(data); // nested structure
let matrix = toMatrix(forest); // 2D array
let html = toHTML(matrix); // <table>
document.getElementById("container").innerHTML = html;
table { border-collapse: collapse }
td { border: 1px solid; font-size: smaller }
<div id="container"></div>
For selection, you would find the node first in the forest , and then pass the found node to the toMatrix function.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | trincot |

