I have the array:
array = [ { "id": 1, "date": { "id": 1, "name": "202001" }, "item": { "id": 1, "name": "I1" }, "price": 100 }, { "id": 2, "date": { "id": 2, "name": "202002" }, "item": { "id": 1, "name": "I1" }, "price": 200 }, { "id": 3, "date": { "id": 2, "name": "202002" }, "item": { "id": 2, "name": "I2" }, "price": 300 }, ]
And I want to be able to display the data as shown in the table:
ITEM | 202001 | 202002 | TOTAL |
---|---|---|---|
I1 | 100 | 200 | 300 |
I2 | – | 300 | 300 |
TOTAL | 100 | 500 | 600 |
I tried
const items_dicc = array.reduce((acc, e) => { if (!acc[e["item"]["name"]]) { acc[e["item"]["name"]] = { [e["date"]["name"]]: e["price"] } } else { acc[e["item"]["name"]][e["date"]["name"]] = e["price"] } return acc }, {}) const dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())]
to show the values of each date for the same item, now I need the above to calculate the subtotals and the total.
EDIT: Using @sabbir.alam answer
totalSumPerDate = {}; dates.forEach(date => { const sumOnDate = Object.values(items_dicc).reduce((acc, curr) => { acc = acc + (curr[date]? curr[date] : 0); return acc; }, 0); totalSumPerDate[[date]] = sumOnDate; });
totalSum = Object.values(totalSumPerDate).reduce((acc, curr) => acc+curr, 0);
sumPerItem = {}; Object.keys(items_dicc).forEach(key => { const sum = Object.values(items_dicc[key]).reduce((acc, curr) => acc + curr, 0); sumPerItem[[key]] = sum; });
I did
<table> <thead> <tr> <th>ITEM</th> {dates.map(date => <th>{date}</th>)} <th>TOTAL</th> </tr> </thead> <tbody> { Object.keys(items_dicc).map((item) => { return ( <tr> <td>{item}</td> {dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)} {Object.values(sumPerItem).map((elem,i) => <td>{elem}</td>)} </tr> ) }) } <tr> <td>TOTAL</td> {Object.values(totalSumPerDate).map((elem,i) => <td>{elem}</td>)} <td>{totalSum}</td> </tr> </tbody> </table>
I need to correct how the side subtotals are displayed.
How can I do it, suggestions?
Advertisement
Answer
You can do the following using reduce ,
array = [ { "id": 1, "date": { "id": 1, "name": "202001" }, "item": { "id": 1, "name": "I1" }, "price": 100 }, { "id": 2, "date": { "id": 2, "name": "202002" }, "item": { "id": 1, "name": "I1" }, "price": 200 }, { "id": 3, "date": { "id": 2, "name": "202002" }, "item": { "id": 2, "name": "I2" }, "price": 300 }, ] items_dicc = array.reduce((acc, e) => { if (!acc[e["item"]["name"]]) { acc[e["item"]["name"]] = { [e["date"]["name"]]: e["price"] } } else { acc[e["item"]["name"]][e["date"]["name"]] = e["price"] } return acc }, {}) dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())] totalSumPerDate = {}; dates.forEach(date => { const sumOnDate = Object.values(items_dicc).reduce((acc, curr) => { acc = acc + (curr[date]? curr[date] : 0); return acc; }, 0); totalSumPerDate[[date]] = sumOnDate; }); totalSum = Object.values(totalSumPerDate).reduce((acc, curr) => acc+curr, 0); sumPerItem = {}; Object.keys(items_dicc).forEach(key => { const sum = Object.values(items_dicc[key]).reduce((acc, curr) => acc + curr, 0); sumPerItem[[key]] = sum; }); console.log('Sum per item: ', sumPerItem); console.log('Sum per date: ', totalSumPerDate); console.log('TotalSum: ', totalSum);
Update for subtotal per item,
<table> <thead> <tr> <th>ITEM</th> {dates.map(date => <th>{date}</th>)} <th>TOTAL</th> </tr> </thead> <tbody> { Object.keys(items_dicc).map((item) => { return ( <tr> <td>{item}</td> {dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)} <td>{sumPerItem[item]}</td> </tr> ) }) } <tr> <td>TOTAL</td> {Object.values(totalSumPerDate).map((elem,i) => <td>{elem}</td>)} <td>{totalSum}</td> </tr> </tbody> </table>