My Title seems a bit confusing,
Here's my problem, i want to destructure an array of objects in order to use it's properties in a chartJS Line Graph.
Here's a reproduced array:
[{
"page": "Page 1",
"date": "2021-10-05",
"visitors": 10
}, {
"page": "Page 2",
"date": "2021-10-05",
"visitors": 20
}, {
"page": "Page 3",
"date": "2021-10-05",
"visitors": 30
},{
"page": "Page 1",
"date": "2021-10-04",
"visitors": 40
}, {
"page": "Page 2",
"date": "2021-10-04",
"visitors": 50
}, {
"page": "Page 3",
"date": "2021-10-04",
"visitors": 60
}]
Every entry contains a date (date), a visitors number (visitors) and a page name (page)
For example, if a have 2 dates and 3 pages for whom i want to retrieve the numbers of visitors per date per page. My array returns 6 entries (3 pages for each date) the example above.
So how can get the the number of visits of every page and get one array containing page names & dates only once & the related visits number like:
[ {
page: pageName,
dates: [],
numberOfVisits: [],
},
{
page: pageName,
dates: [],
numberOfVisits: [],
},
{
page: pageName,
dates: [],
numberOfVisits: []
},
]
i tried reducing the array and filtering it according to either the dates or the page names like so:
myArray.reduce((a, c) => {
/* Filtering by date but this returns only one page name */
let filtered = a.filter(el => (el.date === c.date));
/* OR Filtering by page name but this returns only oneDate for each */
/* let filtered = a.filter(el => (el.page === c.page)); */
if (filtered.length > 0) {
/* summing up the number of visits => this works in both cases */
a[a.indexOf(filtered[0])].m_unique_visitors += +c.m_unique_visitors;
} else {
a.push(c);
}
})
return a;
I'd suggest using Array.reduce()
to group dates and visitors by page.
We'd sort the input array to ensure our output is also sorted by date.
The accumulator (acc) will have a property for each page, with a page name, a list of dates and number of visits array.
We'd use Object.values()
to get the final array required.
const a = [{ "page": "Page 1", "date": "2021-10-05", "visitors": 10 }, { "page": "Page 2", "date": "2021-10-05", "visitors": 20 }, { "page": "Page 3", "date": "2021-10-05", "visitors": 30 },{ "page": "Page 1", "date": "2021-10-04", "visitors": 40 }, { "page": "Page 2", "date": "2021-10-04", "visitors": 50 }, { "page": "Page 3", "date": "2021-10-04", "visitors": 60 }]
const sortByDate = ({ date: a}, { date:b }) => Date.parse(a) - Date.parse(b);
const result = Object.values(a.sort(sortByDate).reduce((acc, { page, date, visitors}) => {
acc[page] = acc[page] || { page, dates: [], numberOfVisits: []};
acc[page].dates.push(date);
acc[page].numberOfVisits.push(visitors);
return acc;
}, {}))
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could also structure the output slightly differently, to have a visits
array, each element having a date
and visitors
value.
const a = [{ "page": "Page 1", "date": "2021-10-05", "visitors": 10 }, { "page": "Page 2", "date": "2021-10-05", "visitors": 20 }, { "page": "Page 3", "date": "2021-10-05", "visitors": 30 },{ "page": "Page 1", "date": "2021-10-04", "visitors": 40 }, { "page": "Page 2", "date": "2021-10-04", "visitors": 50 }, { "page": "Page 3", "date": "2021-10-04", "visitors": 60 }]
const sortByDate = ({ date: a}, { date:b }) => Date.parse(a) - Date.parse(b);
const result = Object.values(a.sort(sortByDate).reduce((acc, { page, date, visitors}) => {
acc[page] = acc[page] || { page, visits: [] };
acc[page].visits.push( { date, visitors});
return acc;
}, {}));
console.log('Result:', result);
.as-console-wrapper { max-height: 100% !important; top: 0; }