Home > Blockchain >  is it possible to sum up the properties of an array of objects and to filter it according to another
is it possible to sum up the properties of an array of objects and to filter it according to another

Time:11-05

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;

CodePudding user response:

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; }
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

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; }
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related