Group array of objects by date in javascript
There are three objects like this.
var Object1 = [
{
"data" : "1-1",
"createdAt": "2022-03-01",
},
{
"data" : "1-2",
"createdAt": "2022-03-02",
},
{
"data" : "1-4",
"createdAt": "2022-03-04",
},
{
"data" : "1-5",
"createdAt": "2022-03-05",
},
{
"data" : "1-6",
"createdAt": "2022-03-06",
},
{
"data" : "1-7",
"createdAt": "2022-03-07",
}
];
var Object2 = [
{
"data" : "2-1",
"createdAt": "2022-03-02",
},
{
"data" : "2-2",
"createdAt": "2022-03-03",
},
{
"data" : "2-3",
"createdAt": "2022-03-04",
},
{
"data" : "2-4",
"createdAt": "2022-03-05",
},
{
"data" : "2-5",
"createdAt": "2022-03-06",
},
{
"data" : "2-6",
"createdAt": "2022-03-07",
},
{
"data" : "2-7",
"createdAt": "2022-03-08",
}
];
var Object3 = [
{
"data" : "3-1",
"createdAt": "2022-03-03",
},
{
"data" : "3-2",
"createdAt": "2022-03-04",
},
{
"data" : "3-3",
"createdAt": "2022-03-05",
},
{
"data" : "3-4",
"createdAt": "2022-03-06",
},
{
"data" : "3-5",
"createdAt": "2022-03-07",
},
{
"data" : "3-6",
"createdAt": "2022-03-08",
},
{
"data" : "3-7",
"createdAt": "2022-03-09",
}
];
And I want to group them like this:
var result = [
{
"Object1" : "1-1",
"Object2" : undefined or null,
"Object3" : undefined or null,
"createdAt": "2022-03-01",
},
{
"Object1" : "1-2",
"Object2" : "2-1",
"Object3" : undefined or null,
"createdAt": "2022-03-02",
},
{
"Object1" : undefined or null,
"Object2" : "2-2",
"Object3" : "3-1",
"createdAt": "2022-03-03",
},
{
"Object1" : "1-4",
"Object2" : "2-3",
"Object3" : "3-2",
"createdAt": "2022-03-04",
},
{
"Object1" : "1-5",
"Object2" : "2-4",
"Object3" : "3-3",
"createdAt": "2022-03-05",
},
{
"Object1" : "1-6",
"Object2" : "2-5",
"Object3" : "3-4",
"createdAt": "2022-03-06",
},
{
"Object1" : "1-7",
"Object2" : "2-6",
"Object3" : "3-5",
"createdAt": "2022-03-07",
},
{
"Object1" : undefined or null,
"Object2" : "2-7",
"Object3" : "3-6",
"createdAt": "2022-03-08",
},
{
"Object1" : undefined or null,
"Object2" : undefined or null,
"Object3" : "3-7",
"createdAt": "2022-03-09",
},
]
I want to group n arrays by date.
However, the dates in each array will also be different, and it is not clear whether there is data or not. The date may be empty in the middle, or the data may be empty. If the hour, minute, and second data are mixed, they are not grouped by date.
I think I can use a foreach loop, but I don't know what I'm missing. Anyone know the answer to this?
CodePudding user response:
This is a fairly standard 'group-by' but since you have multiple arrays and you'd like to use their variable names as properties you'll need a mechanism to do this.
The example below first creates an object from the three arrays using shorthand property names, then iterates the Object.entries()
of this object to group by date assigning data by the variable names as keys. To ensure that all the objects have all the array properties even when they have no relevant entries it creates a template
object from the Object.keys()
of your combined object and spreading it into each accumulator in the group-by operation.
const Object1 = [{ "data": "1-1", "createdAt": "2022-03-01", }, { "data": "1-2", "createdAt": "2022-03-02", }, { "data": "1-4", "createdAt": "2022-03-04", }, { "data": "1-5", "createdAt": "2022-03-05", }, { "data": "1-6", "createdAt": "2022-03-06", }, { "data": "1-7", "createdAt": "2022-03-07", }];
const Object2 = [{ "data": "2-1", "createdAt": "2022-03-02", }, { "data": "2-2", "createdAt": "2022-03-03", }, { "data": "2-3", "createdAt": "2022-03-04", }, { "data": "2-4", "createdAt": "2022-03-05", }, { "data": "2-5", "createdAt": "2022-03-06", }, { "data": "2-6", "createdAt": "2022-03-07", }, { "data": "2-7", "createdAt": "2022-03-08", }];
const Object3 = [{ "data": "3-1", "createdAt": "2022-03-03", }, { "data": "3-2", "createdAt": "2022-03-04", }, { "data": "3-3", "createdAt": "2022-03-05", }, { "data": "3-4", "createdAt": "2022-03-06", }, { "data": "3-5", "createdAt": "2022-03-07", }, { "data": "3-6", "createdAt": "2022-03-08", }, { "data": "3-7", "createdAt": "2022-03-09", }];
const objects = { Object1, Object2, Object3 };
const template = Object.fromEntries(Object.keys(objects).map(k => [k, undefined]));
const grouped = {};
for (const [objGroup, objArr] of Object.entries(objects)) {
for (const { createdAt, data } of objArr) {
const group = grouped[createdAt] ??= { ...template, createdAt };
group[objGroup] = data;
}
}
const result = Object.values(grouped);
console.log(result);
As for your vague statement, 'The date may be empty in the middle, or the data may be empty. If the hour, minute, and second data are mixed, they are not grouped by date', there's nothing to be added without actual data, but you'll need to settle on a stable property to accurately group by.