This is a follow up question to the following question:
Javascript Equivalent to C# LINQ Select
We are using Angular 2 + TypeScript:
I have an Array of objects. Each object in the array include a property called 'StudentType'.
I need to run a C# LINQ style query that extract a list of StudentType in the array and number of array members with that particular type.
While I can do an old school loop and do this, I wonder if there is a better way of doing this, like what C# LINQ GroupBy offers.
Since we are using Angular 2, the use of JQuery is not allowed by the project leads.
I just made up some studentType values for testing but you can use Array.prototype.reduce() to iterate over each element of the input array and add or manipulate properties of an accumulator object.
let arr = [{
    studentType: 'freshman'
  },
  {
    studentType: 'senior'
  },
  {
    studentType: 'sophomore'
  },
  {
    studentType: 'freshman'
  },
  {
    studentType: 'junior'
  },
  {
    studentType: 'senior'
  },
  {
    studentType: 'sophomore'
  },
  {
    studentType: 'freshman'
  },
  {
    studentType: 'sophomore'
  },
  {
    studentType: 'freshman'
  }
];
let result = arr.reduce((prev, curr) => {
  isNaN(prev[curr.studentType]) ? prev[curr.studentType] = 1 : prev[curr.studentType]++;
  return prev;
}, {});
console.log(result);I created a groupBy function in TypeScript.
export interface Group {
  key: any;
  items: any[];
}
export interface GroupBy {
  keys: string[];
  thenby?: GroupBy;
}
export const groupBy = (array: any[], grouping: GroupBy): Group[] => {
  const keys = grouping.keys;
  const groups = array.reduce((groups, item) => {
    const group = groups.find(g => keys.every(key => item[key] === g.key[key]));
    const data = Object.getOwnPropertyNames(item)
      .filter(prop => !keys.find(key => key === prop))
      .reduce((o, key) => ({ ...o, [key]: item[key] }), {});
    return group
      ? groups.map(g => (g === group ? { ...g, items: [...g.items, data] } : g))
      : [
          ...groups,
          {
            key: keys.reduce((o, key) => ({ ...o, [key]: item[key] }), {}),
            items: [data]
          }
        ];
  }, []);
  return grouping.thenby ? groups.map(g => ({ ...g, items: groupBy(g.items, grouping.thenby) })) : groups;
};
I made a demo of it on StackBlitz at
https://stackblitz.com/edit/typescript-ezydzv
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With