Home > Mobile >  groupe Array by multiple columns
groupe Array by multiple columns

Time:10-05

i have this array

i want to store it on new array groupped by date and shift with new column totale of shifts per date

const arr = [
       { sum: 77, shift:  1, date: "2020-07-05T00:00:00" },

       { sum: 25, shift:  2, date: "2020-07-05T00:00:00" },

       { sum: 05, shift:  2, date: "2020-07-05T00:00:00" },

       { sum: 15, shift:  2, date: "2020-07-05T00:00:00" },

       { sum: 10, shift:  3, date: "2020-07-05T00:00:00" },

       { sum: 13, shift:  1, date: "2020-07-06T00:00:00" },

       { sum: 66, shift:  2, date: "2020-07-06T00:00:00" },

       { sum: 30, shift:  3, date: "2020-07-06T00:00:00" },

       { sum: 50, shift:  1, date: "2020-07-07T00:00:00" },

       { sum: 40, shift:  2, date: "2020-07-07T00:00:00" },
     ];

i already calculed totals but i dont know how to groupe by date and shift

i want an output like this

date shift 1 shift 2 shift 3 totale
07-05-2020 77 45 10 132
07-06-2020 13 66 30 109
07-07-2020 50 40 90

i tried this but not returning the correct values

const grouped = arr.reduce((acc, { sum, shift, date }) => {
  let dateKey = date.slice(0, 10);
  acc[dateKey] = acc[dateKey] || {};
  acc[dateKey][`Shift${shift}`] = sum;
  acc[dateKey].total = (acc[dateKey].total || 0)   sum;
  return acc;
}, {});

CodePudding user response:

I think this function is what you need.

const computeArray = (arr) => {
  const result = {}
  arr.forEach(item => {
    const field = `shift${item.shift}`
    if(!result[item.date]) {
      result[item.date] = {}
    }
    result[item.date][field] = (result[item.date][field] || 0)   item.sum
    result[item.date].total = (result[item.date].total || 0)   item.sum
  })

  return Object.keys(result).map(key => ({
    date: key,
    ...result[key]
    
  }))
}

CodePudding user response:

Using reduce method as below

const arr = [
       { sum: 77, shift:  1, date: "2020-07-05T00:00:00" },

       { sum: 25, shift:  2, date: "2020-07-05T00:00:00" },

       { sum: 05, shift:  2, date: "2020-07-05T00:00:00" },

       { sum: 15, shift:  2, date: "2020-07-05T00:00:00" },

       { sum: 10, shift:  3, date: "2020-07-05T00:00:00" },

       { sum: 13, shift:  1, date: "2020-07-06T00:00:00" },

       { sum: 66, shift:  2, date: "2020-07-06T00:00:00" },

       { sum: 30, shift:  3, date: "2020-07-06T00:00:00" },

       { sum: 50, shift:  1, date: "2020-07-07T00:00:00" },

       { sum: 40, shift:  2, date: "2020-07-07T00:00:00" },
     ];
     
const res = Object.values(arr.reduce((acc,curr)=>{
  // create an object with `date` as key and value as `curr` if `date` is not present in `acc`
  if(!acc[curr.date]){
    const {date} = curr;
     acc[curr.date] = {date};
  }
  
  // add "sum" if same shift found
  if(acc[curr.date][`shift${curr.shift}`]){
    acc[curr.date][`shift${curr.shift}`]  = curr.sum;
  }else{
    acc[curr.date][`shift${curr.shift}`] = curr.sum
  }
  
  // for total
  if(!acc[curr.date].total){
    acc[curr.date].total = curr.sum;
  }else{
    acc[curr.date].total  = curr.sum;
  }
  
  return acc
},{}))

console.log(res)

CodePudding user response:

You had an almost complete solution. I just slightly modified it.

const arr = [{ sum: 77, shift:  1, date: "2020-07-05T00:00:00" },{ sum: 25, shift:  2, date: "2020-07-05T00:00:00" },{ sum: 05, shift:  2, date: "2020-07-05T00:00:00" },{ sum: 15, shift:  2, date: "2020-07-05T00:00:00" },{ sum: 10, shift:  3, date: "2020-07-05T00:00:00" },{ sum: 13, shift:  1, date: "2020-07-06T00:00:00" },{ sum: 66, shift:  2, date: "2020-07-06T00:00:00" },{ sum: 30, shift:  3, date: "2020-07-06T00:00:00" },{ sum: 50, shift:  1, date: "2020-07-07T00:00:00" },{ sum: 40, shift:  2, date: "2020-07-07T00:00:00" },];

const grouped = arr.reduce((acc, { sum, shift, date }) => {
  const shiftName = `Shift${shift}`;
  acc[date] ??= { date, total: 0 };
  acc[date].total  = sum;
  acc[date][shiftName] ??= 0;
  acc[date][shiftName]  = sum;
  return acc;
}, {});
const result = Object.values(grouped);

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0 }

  • Related