Reputation: 43
Ok, so I have an array of objects that look like that
{id: 1, color: "red", size: "S", free: 14, location: "Location #1"}
{id: 2, color: "green", size: "M", free: 5, location: "Location #1"}
{id: 3, color: "red", size: "M", free: 3, location: "Location #2"}
{id: 4, color: "green", size: "L", free: 12, location: "Location #1"}
{id: 5, color: "green", size: "S", free: 5, location: "Location #2"}
{id: 6, color: "red", size: "L", free: 0, location: "Location #1"}
{id: 7, color: "blue", size: "L", free: 0, location: "Location #2"}
{id: 8, color: "blue", size: "M", free: 0, location: "Location #1"}
{id: 9, color: "blue", size: "S", free: 0, location: "Location #1"}
{id: 10, color: "purple", size: "L", free: 0, location: "Location #2"}
And I want to be able to generate a table that would look something like that
I suppose that i have to filter or group some of the key-value pairs or something like that but i don't know the right way to approach this.
Again maybe for this particular table I have to do something like this:
{
color: 'red',
location: 'Location #1',
sizes: [
{
s: 12
},
{
m: 5
},
{
l: 7
}
]
}
{
color: 'green',
location: 'Location #1',
sizes: [
{
s: 3
},
{
m: 11
},
{
l: 4
}
]
}
But then i have to figure out how to populate the HTML table itself with this data. Maybe there is some library or something that would help me do that. Thanks!
Upvotes: 1
Views: 724
Reputation: 13983
See the table generated at the end
You can use reduce to accumulate the sizes for each color and each location. Here is an example way to use reduce
and the resulting tree.
const tree = data.reduce((accum, { id, color, size, free, location }) => {
accum[location] = accum[location] || { };
accum[location][color] = accum[location][color] || { S: 0, M: 0, L: 0 };
accum[location][color][size] += free;
return accum;
}, {});
{
"Location #1": {
"red": {
"S": 14,
"M": 0,
"L": 0
},
"green": {
"S": 0,
"M": 5,
"L": 12
},
"blue": {
"S": 0,
"M": 0,
"L": 0
}
},
"Location #2": {
"red": {
"S": 0,
"M": 3,
"L": 0
},
"green": {
"S": 5,
"M": 0,
"L": 0
},
"blue": {
"S": 0,
"M": 0,
"L": 0
},
"purple": {
"S": 0,
"M": 0,
"L": 0
}
}
}
To create the table, you can iterate over the location entries, and for each location iterate over the colors, then append the rows to the table.
You can create each row by cloning a row template that you query from the DOM, then append that row to your table body:
const data = [
{id: 1, color: "red", size: "S", free: 14, location: "Location #1"},
{id: 2, color: "green", size: "M", free: 5, location: "Location #1"},
{id: 3, color: "red", size: "M", free: 3, location: "Location #2"},
{id: 4, color: "green", size: "L", free: 12, location: "Location #1"},
{id: 5, color: "green", size: "S", free: 5, location: "Location #2"},
{id: 6, color: "red", size: "L", free: 0, location: "Location #1"},
{id: 7, color: "blue", size: "L", free: 0, location: "Location #2"},
{id: 8, color: "blue", size: "M", free: 0, location: "Location #1"},
{id: 9, color: "blue", size: "S", free: 0, location: "Location #1"},
{id: 10, color: "purple", size: "L", free: 0, location: "Location #2"}
];
const tree = data.reduce((accum, { id, color, size, free, location }) => {
accum[location] = accum[location] || { };
accum[location][color] = accum[location][color] || { S: 0, M: 0, L: 0 };
accum[location][color][size] += free;
return accum;
}, {});
const tpl = document.querySelector('#row-template');
const tbody = document.querySelector("tbody");
Object.entries(tree).forEach(([location, values]) => {
Object.entries(values).forEach(([color, sizes]) => {
const clone = document.importNode(tpl.content, true);
const td = clone.querySelectorAll("td");
td[0].textContent = location;
td[1].textContent = color;
td[2].textContent = sizes['S'];
td[3].textContent = sizes['M'];
td[4].textContent = sizes['L'];
tbody.appendChild(clone);
});
});
table {
border-collapse: collapse;
}
thead {
font-weight: bold;
}
td {
padding: 5px;
border: 1px solid black;
}
<template id="row-template">
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</template>
<table id="data-table">
<thead>
<tr>
<td>Location</td><td>color</td><td>S</td><td>M</td><td>L</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
Upvotes: 1
Reputation: 386868
You could build a tree and collect al value you have in your data set. The result is a tree where the keys are the location
, color
and size
values. At the leaves, you get the accumulated value of free
.
Then you could build a array for the table with the accumulated values.
function getTable(object) {
function getRows(object, row = []) {
if (row.length === 2) {
table.push(row.concat(['S', 'M', 'L'].map(k => object[k] || 0)));
return;
}
Object.entries(object).forEach(([k, v]) => getRows(v, row.concat(k)));
}
var table = [];
getRows(object);
return table;
}
var data = [{ id: 1, color: "red", size: "S", free: 14, location: "Location #1" }, { id: 2, color: "green", size: "M", free: 5, location: "Location #1" }, { id: 3, color: "red", size: "M", free: 3, location: "Location #2" }, { id: 4, color: "green", size: "L", free: 12, location: "Location #1" }, { id: 5, color: "green", size: "S", free: 5, location: "Location #2" }, { id: 6, color: "red", size: "L", free: 0, location: "Location #1" }, { id: 7, color: "blue", size: "L", free: 0, location: "Location #2" }, { id: 8, color: "blue", size: "M", free: 0, location: "Location #1" }, { id: 9, color: "blue", size: "S", free: 0, location: "Location #1" }, { id: 10, color: "purple", size: "L", free: 0, location: "Location #2" }],
tree = data.reduce((r, o) => {
var q = ['location', 'color'].reduce((p, k) => p[o[k]] = p[o[k]] || {}, r);
q[o.size] = (q[o.size] || 0) + o.free;
return r;
}, {}),
table = getTable(tree);
console.log(tree);
console.log(table);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1