i have the following array instance
this.array=[{id:"121",score:"5",createdOn:"2022-05-17T19:52:23.6846702 00:00"}
{id:"121",score:"8",createdOn:"2022-05-19T13:00:00.6846702 00:00"}
{id:"122",score:"7",createdOn:"2022-04-11T08:00:00.6846702 00:00"}
{id:"121",score:"1",createdOn:"2022-03-12T12:00:00.6846702 00:00"}
]
how do i some the values with a matching id and month. for example my ouput should be
newArray=[{id:"121",score:13,month:"May"}
{id:"122",score:7,month:"April"}
{id:"121",score:1,month:"March"}
]
i tried something like this
this.array.forEach(item => {
var obj = {}
if (obj.hasOwnProperty(item.id)) {
obj["id"] = obj[item.id] parseFloat(item.score);
}
else {
obj["id"] = parseFloat(item.score);
}
this.newArray.push(obj);
});
But it didnt work and i dont know how to check the month
CodePudding user response:
You can use a fairly standard 'group by' using a compound key of id_month
.
The example uses reduce()
to iterate the array, toLocaleDateString()
to retrieve the month name from the ISO date string and a template literal to create the compound key.
The score
should be converted to a number before adding to avoid accidental concatenation, here using the unary plus ( ) operator.
Finally we take just the Object.values
of the grouped object as the result.
const array = [{ id: "121", score: "5", createdOn: "2022-05-17T19:52:23.6846702 00:00" }, { id: "121", score: "8", createdOn: "2022-05-19T13:00:00.6846702 00:00" }, { id: "122", score: "7", createdOn: "2022-04-11T08:00:00.6846702 00:00" }, { id: "121", score: "1", createdOn: "2022-03-12T12:00:00.6846702 00:00" },];
const result = Object.values(
array.reduce((a, { id, createdOn, score, ...rest }) => {
const month = new Date(createdOn).toLocaleDateString('en', { month: 'long' });
a[`${id}_${month}`] ??= { id, month, score: 0, ...rest };
a[`${id}_${month}`].score = score;
return a;
}, {})
)
console.log(result)
The exact same logic can be used in a standard for...of
loop instead of within a reduce()
call if you prefer.
const array = [{ id: "121", score: "5", createdOn: "2022-05-17T19:52:23.6846702 00:00" }, { id: "121", score: "8", createdOn: "2022-05-19T13:00:00.6846702 00:00" }, { id: "122", score: "7", createdOn: "2022-04-11T08:00:00.6846702 00:00" }, { id: "121", score: "1", createdOn: "2022-03-12T12:00:00.6846702 00:00" },];
const grouped = {}
for (const { id, createdOn, score, ...rest } of array) {
const month = new Date(createdOn).toLocaleDateString('en', { month: 'long' });
grouped[`${id}_${month}`] ??= { id, month, score: 0, ...rest }
grouped[`${id}_${month}`].score = score;
}
const result = Object.values(grouped);
console.log(result)
CodePudding user response:
Use a temporary object to hold the updated information.
Because you need to separate out the objects that have the same ids but that were created on different months you can use a key
id-month
on the temporary object to identify them.Loop over the array of objects getting the month name, and create the key. (I've used
Intl.DateTimeFormat
here because you can pass in a language string to get a different result from the function - try'es-ES'
for example.)If the property with that key doesn't exist on the temporary object add a default object to the temporary object with a default object value, and then increase its
score
(making sure you coerce it to a number first).Finally get the
Object.values
which will return an array of all those values in the temporary object.
const arr=[{id:"121",score:"5",createdOn:"2022-05-17T19:52:23.6846702 00:00"},{id:"121",score:"8",createdOn:"2022-05-19T13:00:00.6846702 00:00"},{id:"122",score:"7",createdOn:"2022-04-11T08:00:00.6846702 00:00"},{id:"121",score:"1",createdOn:"2022-03-12T12:00:00.6846702 00:00"}];
const temp = {};
const language = 'en-GB';
function getMonth(createdOn, language) {
const date = new Date(createdOn);
return new Intl.DateTimeFormat(language, { month: 'long' }).format(date);
}
for (const obj of arr) {
const { id, score, createdOn } = obj;
const month = getMonth(createdOn, language);
const key = `${id}-${month}`;
temp[key] ??= { id, score: 0, month };
temp[key].score = Number(score);
}
console.log(Object.values(temp));
Additional documentation