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?