Home > Software design >  how do i sum up a value from an array depending on the date and id
how do i sum up a value from an array depending on the date and id

Time:05-19

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:

  1. Use a temporary object to hold the updated information.

  2. 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.

  3. 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.)

  4. 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).

  5. 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

  • Related