Home > front end >  How to group by and sum an array of objects javascript?
How to group by and sum an array of objects javascript?

Time:05-20


const array = [
  {
      "data": {
          "qty": "5",
          "toy": {
              "id": 3,
          },
          "available": "yes",
      }
  },
  {
      "data": {
          "qty": "5",
          "toy": {
              "id": 10,
          },
          "available": "no"
      }
  },
  {
      "data": {
          "qty": "59",
          "toy": {
              "id": 10,
          },
          "available": "yes",
      }
  },
  {
      "data": {
          "qty": "5",
          "toy": {
              "id": 3,
          },
          "available": "yes",
      }
  }
]


var result = [];
array.reduce(function(res, value) {
  if (!res['data']['toy'] || !res['data']['toy']['data']) {
    res['data'] = {...value['data'] };
    result.push(res['data'])
  }
  if (res['data']['available'] === value['data']['available'] && res['data']['toy']['id'] === value['data']['toy']['id']) {
    res['data']['qty'] = parseInt(res['data']['qty'])   parseInt(value['data'].qty)
  }
  return res;
}, {'data': {}});

console.log(result)

I am working on a js project and I need a bit of help here. From the array, How to get a new array that has qty as the sum of the other qty value which data.toy.id and available same. i.e. I want the below array. My code is not working as excepted. Changes to the same or new code are also fine. Thank you.

const array = [
  {
      "data": {
          "qty": "10",
          "toy": {
              "id": 3,
          },
          "available": "yes",
      }
  },
  {
      "data": {
          "qty": "5",
          "toy": {
              "id": 10,
          },
          "available": "no"
      }
  },
  {
      "data": {
          "qty": "59",
          "toy": {
              "id": 10,
          },
          "available": "yes",
      }
  }
]

CodePudding user response:

You group the array into an object, where the keys are concatenation of available and id properties and finally transform the object back to an array using Object.values.

const 
  array = [
    { data: { qty: "5", toy: { id: 3 }, available: "yes" } },
    { data: { qty: "5", toy: { id: 10 }, available: "no" } },
    { data: { qty: "59", toy: { id: 10 }, available: "yes" } },
    { data: { qty: "5", toy: { id: 3 }, available: "yes" } },
  ],
  result = Object.values(
    array.reduce((r, { data }) => {
      const k = data.available   data.toy.id;
      if (r[k]) {
        r[k].data.qty = String(Number(r[k].data.qty)   Number(data.qty));
      } else {
        r[k] = { data };
      }
      return r;
    }, {})
  );

console.log(result);

CodePudding user response:

I'd suggest using Array.reduce() to group by a key, which will be combined value of the toy id and the available property.

We'd create a map of all toys based on this key, summing the quantity for each.

Finally, we'll use Object.values() to convert back into an array.

const array = [ { "data": { "qty": "5", "toy": { "id": 3, }, "available": "yes", } }, { "data": { "qty": "5", "toy": { "id": 10, }, "available": "no" } }, { "data": { "qty": "59", "toy": { "id": 10, }, "available": "yes", } }, { "data": { "qty": "5", "toy": { "id": 3, }, "available": "yes", } } ];

const result = Object.values(array.reduce((acc, { data: { qty, toy, available } }) => { 
    const key = `${toy.id}-${available}`;
    acc[key] = acc[key] || { data: { qty: 0, toy, available } };
    acc[key].data.qty  = Number(qty);
    return acc;
}, {}))

console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

CodePudding user response:

You can use Array#reduce() to create arrayHash object using as keys: ${c.data.toy.id}-${c.data.available}

Code:

const array = [{data: {qty: '5',toy: {id: 3,},available: 'yes',},},{data: {qty: '5',toy: {id: 10,},available: 'no',},},{data: {qty: '59',toy: {id: 10,},available: 'yes',},},{data: {qty: '5',toy: {id: 3,},available: 'yes',},},]

const arrayHash = array.reduce((a, { data }) => {
  const key = `${data.toy.id}-${data.available}`
  a[key] = a[key] || { data: { ...data, qty: 0 } }
  a[key].data.qty = ( a[key].data.qty    data.qty).toString();
  return a
}, {})
const result = Object.values(arrayHash)

console.log(result)

CodePudding user response:

I'd use just reduce

const a1 = [
  {
      "data": {
          "qty": "5",
          "toy": {
              "id": 3,
          },
          "available": "yes",
      }
  },
  {
      "data": {
          "qty": "5",
          "toy": {
              "id": 10,
          },
          "available": "no"
      }
  },
  {
      "data": {
          "qty": "59",
          "toy": {
              "id": 10,
          },
          "available": "yes",
      }
  },
  {
      "data": {
          "qty": "5",
          "toy": {
              "id": 3,
          },
          "available": "yes",
      }
  }
]

const a2 = a1.reduce((acc, it) => {
  let found = acc.find(
    dp => dp.data.toy.id === it.data.toy.id && dp.data.available === it.data.available
  )
  if(found){
    found.data.qty = ( Number(found.data.qty)   Number(it.data.qty) ).toString()
  }
  else acc.push(it)
  return acc
}, [])

console.log(JSON.stringify(a2, null,2))

  • Related