I've an array of objects and I want to convert it into a visual table in HTML; so I did it last night, but I was tired. I don't think it is the right way of doing it, even though it's working and gives the expected result.
let notes = [ { note: "n1", subject: "subject1", value: 10 }, { note: "n2", subject: "subject2", value: 15 }, { note: "n2", subject: "subject2", value: 5 }, { note: "n3", subject: "subject2", value: 20 }, ]; function make_matrix(objs) { let rows = [...new Set(objs.map(({ subject }) => subject))]; let columns = [...new Set(objs.map(({ note }) => note))]; let array_objs = {}; for (const obj of objs) { let { note, subject, value } = obj; if (array_objs[subject + "-" + note]) array_objs[subject + "-" + note] = [ ...array_objs[subject + "-" + note], obj, ]; else array_objs[subject + "-" + note] = [obj]; } for (const [k, v] of Object.entries(array_objs)) { total = v.map(({ value }) => +value).reduce((a, b) => a + b); array_objs[k] = total; } let od = {}; for (const [k, v] of Object.entries(array_objs)) { const [key, value] = k.split("-"); if (od[key]) { od[key] = [...od[key], { [value]: v }]; } else { od[key] = [{ [value]: v }]; } } let trs = ""; for (const [key, value] of Object.entries(od)) { trs += "<tr><th>" + key + "</th>"; for (const col of columns) { const entry = value .map((x) => Object.entries(x)[0]) .find((x) => x[0] == col); if ( value .map((x) => Object.entries(x)[0]) .map((x) => x[0]) .includes(col) ) { trs += "<td>" + entry[1] + "</td>"; } else { trs += "<td>0</td>"; } } trs += "</tr>"; } let table = `<table> <tr><th>Subjects</th><th>${columns.join( "</th><th>" )}</th></tr> ${trs} </table>`; return table; } document.querySelector(".content").innerHTML = make_matrix(notes);
table { border-collapse: collapse; border: 1px solid; } tr, th, td { border: 1px solid; padding: 3px 10px; }
<div class="content"></div>
Is it the right way of doing it?