Find and map together data in an Array

Viewed 52

I need to map and gather the name - sum values from an array, but I don't know what the best solution would be here and I got stuck. The data that I get looks like this:

{
timestamp:"2022-09-15",
management: [
{ id: 1;
  name: Sam;
  sum: 12;
},
{ id: 2;
  name: Sam;
  sum: 20;
},
{ id: 3;
  name: Sam;
  sum: 30;
},
{ id: 4;
  name: Sam;
  sum: null;
},
{ id: 5;
  name: Mae;
  sum: 456;
}]

What I would like to achieve is this output:

this.labels = ["Sam", "Mae"];
this.sums = [ 62, 456];

So I would like to find and add all sum values that Sam has, and all values that Mae has, and gather them in an array. What would be the recommended way to do this? What I have tried:

interface FinancesUI {
  timestamp: string;
  management: ProductUI[];
}

interface ProductUI {
  id: number;
  name: string;
  sum: number;
}

finances: FinancesUI;
labels = string[];
sums = number[];

  ngOnInit() {
    this.financesService.getProducts()
     .subscribe({
      next: (financesUI: FinancesUI) => {
        this.finances = financesUI;
        
        const allNames = this.finances.management.map((data) => data.name);
        const getSum = this.finances.management.map((data) => data.sum);
        this.labels = [...new Set(allNames)];

        this.finances.management.forEach((management, i = 0) => {
            if (management.name === this.labels[i]) {
              this.sums.push(management.sum);
            }
          })
      }, 
      error: (error) => {
        ...
    }
  });
  }


I get an error "Cannot read property 'push' of undefined". Can someone please help me?

3 Answers

Generally speaking. groupBy name and then take the sum for each group.

// like groupBy, but a bit more versatile due to the reducer.
function aggregate(list, getKey, reducer) {
  const map = new Map();
  for (const item of list) {
    const key = getKey(item);
    map.set(key, reducer(map.get(key), item));
  }
  return map;
}


const data = [
  { id: 1, name: "Sam", sum: 12 },
  { id: 2, name: "Sam", sum: 20 },
  { id: 3, name: "Sam", sum: 30 },
  { id: 4, name: "Sam", sum: null },
  { id: 5, name: "Mae", sum: 456 }
];

const sumsByName = aggregate(
  data, 
  item => item.name, //group by Name
  (total=0, item) => total + (+item.sum)  // aggregate some value per group
);

console.log("labels", [...sumsByName.keys()]);
console.log("sums", [...sumsByName.values()]);

this.sums?.push(person.sum);

try adding {?} after sums

Related