Search code examples
javascriptarraysdategrouping

Javascript group array of object by near dates


i can't understand how to group an array of object inside a timeline.

Let me explain,

the timeline is created from a range of dates, it reach +90 year from the start date.

const timeline = [
    {
        year: '2015',
        items: []
    },
    {
        year: '2016',
        items: []
    }
];

Inside the timeline.items i have to push other items coming from another array of objects, timelineItems

const timelineItems = [
    {
        year: '2015',
        somedata:'somevalue'
    },
    {
        year: '2016',
        somedata:'somevalue'
    }
];

In some situations, i have to group those values, based on the diff from the timeline.year and the timlineItems.year

This is the expected results

const timeline = [{
        year: '2015',
        items: [{
                year: '2015',
                somedata: 'somevalue'
            },
            {
                year: '2016',
                somedata: 'somevalue'
            }
        ]
    },
    {
        year: '2016',
        items: []

    }
];

I am trying to map the timeline.items with a function who check the difference between the first year found and the next 3 years, but i'm having some problem. I still don't understand how to do this.

I've made this https://jsfiddle.net/ghmtL8cf/ with the initial data and some comments to help understand the desired output.

UPDATE

Thanks to @Nur answer i was able to perform the first grouping.

This is the link of the updated jsfiddle with more input and a expected output.

In the expected output i would like to have the grouping applied only if the first timelineItems is equal to the actual timeline year.

Looking at the problem i would like to add another idea.

Should we split the timeline inside chunk of 3 and for each chunk add the timelineItems equal to the start-end of the chunk years?

Thanks in advance


Solution

  • This is a tricky problem. At first Check if timelineItems exist in timelineRef, if it doesn't then create a ref and push item into timeline, else find the timeline from timelineRef then push item and continue loop...

    It should solve your problem, And this is super efficient!

    let timeline = [{ year: '2015', items: [] }, { year: '2016', items: [] }, { year: '2019', items: [] }, { year: '2023', items: [] }, { year: '2024', items: [] }, { year: '2025', items: [] }, { year: '2026', items: [] }],
        timelineItems = [{ year: '2015', somedata: 'somevalue' }, { year: '2016', somedata: 'somevalue' }, { year: '2019', somedata: 'somevalue' }, { year: '2023', somedata: 'somevalue' }, { year: '2024', somedata: 'somevalue' }, { year: '2025', somedata: 'somevalue' }];
    
    function group(timeline, timelineItems) {
        const timelineRef = [];
        loop: for (const item of timelineItems) {
            for (const { year, items } of timelineRef)
                if (year < item.year && item.year < year + 3) {
                    items.push(item);
                    continue loop;
                }
    
            for (const { year, items } of timeline) {
                if (year != item.year) continue;
                items.push(item);
                timelineRef.push({ year: Number(year), items });
                break;
            }
        }
        return timeline;
    }
    console.log(group(timeline, timelineItems));