Quentin
Quentin

Reputation: 1933

How to group the elements of a list to form a new list

I am receiving data from my API like this:

[
  {grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"},
  {grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1"},
  {grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1,  type: "Type_1"},
  {grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2"},
  {grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 26, type: "Type_2"}
]

Thanks to a StackOverflow post, I managed to transform my list to group each item by type like this:

var API_DATA = [
  {grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"},
  {grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1"},
  {grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1,  type: "Type_1"},
  {grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2"},
  {grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 26, type: "Type_2"}
];

Array.prototype.groupBy = function(k) {
      return this.reduce((acc, item) => ((acc[item[k]] = [...(acc[item[k]] || []), item]), acc),{});
};

TABLE_DATA = API_DATA.groupBy("type")
console.log(TABLE_DATA)

Unfortunately, I cannot use this result in a dataSource of an angular material mat-table because it is not a list:

Error: Provided data source did not match an array, Observable, or DataSource

How can I retrieve a list consisting of several lists:

[
  [
    {grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"},
    {grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1"},
    {grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1,  type: "Type_1"}
  ],
  [
    {grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2"},
    {grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 26, type: "Type_2"}
  ]
]

Thanks for your help.

Upvotes: 3

Views: 92

Answers (4)

Nina Scholz
Nina Scholz

Reputation: 386560

You could get the values form the object.

Array.prototype.groupBy = function(k) {
    return this.reduce((acc, item) => (acc[item[k]] = [...(acc[item[k]] || []), item], acc), {});
};

var API_DATA = [{ grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1" }, { grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1" }, { grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1,  type: "Type_1" }, { grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2" }, { grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 26, type: "Type_2" }],
    TABLE_DATA = Object.values(API_DATA.groupBy("type"));

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

UPDATE 2023

With new standard Object.groupBy:

const
    API_DATA = [{ grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1" }, { grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1" }, { grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1,  type: "Type_1" }, { grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2" }, { grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 26, type: "Type_2" }],
    TABLE_DATA = Object.values(Object.groupBy(API_DATA, ({ type }) => type));

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

Upvotes: 2

dpmemcry
dpmemcry

Reputation: 117

you can use _.groupBy() function on lodash

var jsonArray = [
  {grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"},
  {grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1"},
  {grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1,  type: "Type_1"},
  {grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2"},
  {grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 26, type: "Type_2"}
]


var groupJson= _.groupBy(jsonArray, function(jsonArray) {
  return jsonArray.type;
});

console.log(groupJson);
<script src='https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js'></script>

Upvotes: 0

Ahmed ElMetwally
Ahmed ElMetwally

Reputation: 2383

You can group this data by two ways.

  • First way is grouping to object
  • Second way is grouping to array

Demo

NOTE: I'm using JSON.stringify(group, null, 2). to just prettify the output.

const API_DATA = [
    { grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1" },
    { grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1" },
    { grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1, type: "Type_1" },
    { grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2" },
    { grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 26, type: "Type_2" }
];

const groupBy = 'type';

console.log('------------------');
console.log('------Object------');
console.log('------------------');

const group1 = {};
for (let i = 0; i < API_DATA.length; i++) {
    const element = API_DATA[i];
    const groupByValue = element[groupBy];

    if (typeof group1[groupByValue] === 'undefined') {
        group1[groupByValue] = [element];
    } else {
        group1[groupByValue].push(element);
    }
}
console.log(JSON.stringify(group1, null, 2))




console.log('-------------------');
console.log('-------Array-------');
console.log('-------------------');

const group2 = [];
const tmp = {};
for (let i = 0; i < API_DATA.length; i++) {
    const element = API_DATA[i];
    const groupByValue = element[groupBy];

    if (typeof tmp[groupByValue] === 'undefined') {
        const position = group2.length; // get new position
        tmp[groupByValue] = position; // save it
        group2[position] = [element];
    } else {
        const position = tmp[groupByValue];
        group2[position].push(element);
    }
}
console.log(JSON.stringify(group2, null, 2))

Upvotes: 1

Alex113
Alex113

Reputation: 58


    Array.prototype.groupBy = function (k) {
      return this.reduce(
        (acc, item) => ((acc[item[k]] = [...(acc[item[k]] || []), item]), acc),
        []
      );
    };

Upvotes: 0

Related Questions