Home > Mobile >  Group array nested value with reduce
Group array nested value with reduce

Time:12-07

I need to group the array with a nested value type.Id. How to change the current groupby function to achieve this. Current function will group using the productName or Price. Need to group using a nested value type.id Any help would be greatly appreciated!

Group by function

static groupBy<T>(data: T[], key: string): T[] {
        return <T[]>data.reduce((a, b) => {
            (a[b[key]] = a[b[key]] || []).push(x);
            return <T[]>a;
        }, {});
    }

sample value:

var sales = [
{
   "productName": "AAA",
   "type": {
       "id": 1,
       "name": "Soap"
   },
   "price": 90
},
{
   "productName": "BBB",
   "type": {
       "id": 1,
       "name": "Soap"
   },
   "price": 85
},
{
   "productName": "CCC",
   "type": {
       "id": 1,
       "name": "Soap"
   },
   "price": 55
},
{
   "productName": "DDD",
   "type": {
       "id": 2,
       "name": "shampoo"
   },
   "price": 2
},
{
   "productName": "EEE",
   "type": {
       "id": 2,
       "name": "shampoo"
   },
   "price": 5
}
]

Expected Result:

{1}, 
[
{
   "productName": "AAA",
   "type": {
       "id": 1,
       "name": "Soap"
   },
   "price": 90
},
{
   "productName": "BBB",
   "type": {
       "id": 1,
       "name": "Soap"
   },
   "price": 85
},
{
   "productName": "CCC",
   "type": {
       "id": 1,
       "name": "Soap"
   },
   "price": 55
}],

{2},[
{
   "productName": "DDD",
   "type": {
       "id": 2,
       "name": "shampoo"
   },
   "price": 2
},
{
   "productName": "EEE",
   "type": {
       "id": 2,
       "name": "shampoo"
   },
   "price": 5
}
]

CodePudding user response:

Updated groupBy function:

static groupBy<T>(data: T[], key: string): T[] {
  return <T[]>data.reduce((a, b) => {
      (a[b[key].id] = a[b[key].id] || []).push(x);
      return <T[]>a;
  }, {});
}

CodePudding user response:

Add an accessor function to use properties at any depth,

function groupBy<T>(data: T[], key: string): T[] {

  const path: string[] = key.split('.');
  const accessor = (obj: T) => {
    return path.reduce((x,y) => {
      return x[y]
    }, obj).toString();
  }

  return <T[]>data.reduce((a, b) => {
    const value = accessor(b);
    (a[value] = a[value] || []).push(b);
    return <T[]>a;
  }, {});
}
console.log(groupBy(sales, 'type.id'))

Runnable JS version

const sales = [
  {
    "productName": "AAA",
    "type": {
      "id": 1,
      "name": "Soap"
    },
    "price": 90
  },
  {
    "productName": "BBB",
    "type": {
      "id": 1,
      "name": "Soap"
    },
    "price": 85
  },
  {
    "productName": "CCC",
    "type": {
      "id": 1,
      "name": "Soap"
    },
    "price": 55
  },
  {
    "productName": "DDD",
    "type": {
      "id": 2,
      "name": "shampoo"
    },
    "price": 2
  },
  {
    "productName": "EEE",
    "type": {
      "id": 2,
      "name": "shampoo"
    },
    "price": 5
  }
]

function groupBy(data, key) {

  const path = key.split('.');
  const accessor = (obj) => {
    return path.reduce((x,y) => {
      return x[y]
    }, obj).toString();
  }

  return data.reduce((a, b) => {
    const prop = accessor(b);
    (a[prop] = a[prop] || []).push(b);
    //a[prop] = a[prop] || [];
    //a[prop].push(b);
    return a;
  }, {});
}

console.log(groupBy(sales, 'type.id'))

  • Related