user3887366
user3887366

Reputation: 2594

Javascript array reduce with aggregation key

My goal is from an array object like this:

const data = [
      {
        code: 'prod1',
        quantity: 13,
        pricePerItem: 10,
        totalCost: 130
      },
      {
        code: 'prod1',
        quantity: 7,
        pricePerItem: 11,
        totalCost: 77
      },
      {
        code: 'prod2',
        quantity: 10,
        pricePerItem: 9,
        totalCost: 90
      },
      {
        code: 'prod2',
        quantity: 9,
        pricePerItem: 10,
        totalCost: 90
      },
    ];

build an object with code as key an object with aggregation data like:

{
  prod1:{
     quantity: 20,
     total: 207
  },
  prod2:{
     quantity: 19,
     total:180
  } 
}

Without the object keys is quite easy

data.reduce(
      (acc, current) => {
        return {
          total: acc.total + current.totalCost,
          quantity: acc.quantity + current.quantity
        };
      },
      { total: 0, quantity: 0 }
    );

but with the object keys I'm stuck Could you help me, please?

Upvotes: 1

Views: 209

Answers (4)

Samathingamajig
Samathingamajig

Reputation: 13243

const data = [
  {
    code: 'prod1',
    quantity: 13,
    pricePerItem: 10,
    totalCost: 130
  },
  {
    code: 'prod1',
    quantity: 7,
    pricePerItem: 11,
    totalCost: 77
  },
  {
    code: 'prod2',
    quantity: 10,
    pricePerItem: 9,
    totalCost: 90
  },
  {
    code: 'prod2',
    quantity: 9,
    pricePerItem: 10,
    totalCost: 90
  },
];



let output = data.reduce((acc, val) => ({
  ...acc, // Spread out the accumulator
  [val.code]: {
    // If it doesn't exist yet, make it 0, and add the current val's property
    quantity:  ((acc[val.code] && acc[val.code].quantity ) || 0) + val.quantity,
    totalCost: ((acc[val.code] && acc[val.code].totalCost) || 0) + val.totalCost
  }
}), {});



// Override console.log to make it look the way I want it to look
// This is just aesthetics
console.log = (...args) => {
  for (let arg of args) {
    const pre = document.createElement("pre");
    pre.innerText = JSON.stringify(arg, null, 2);
    document.querySelector("body").appendChild(pre);
  }
};
// --------------------------
// --------------------------

console.log(output)
html,
body {
  background: whitesmoke;
}

pre {
  color: black;
  background: white;
  padding: 1rem;
  border: 2px solid black;
  border-radius: 1rem;
}

Upvotes: 0

Valentin Briand
Valentin Briand

Reputation: 3683

const data = [
  {
    code: "prod1",
    quantity: 13,
    pricePerItem: 10,
    totalCost: 130
  },
  {
    code: "prod1",
    quantity: 7,
    pricePerItem: 11,
    totalCost: 77
  },
  {
    code: "prod2",
    quantity: 10,
    pricePerItem: 9,
    totalCost: 90
  },
  {
    code: "prod2",
    quantity: 9,
    pricePerItem: 10,
    totalCost: 90
  }
];

console.log(
  data.reduce((acc, current) => {
    if (!acc[current.code]) {
      acc[current.code] = { quantity: 0, total: 0 };
    }
    return {
      ...acc,
      [current.code]: {
        quantity: acc[current.code].quantity + current.quantity,
        total: acc[current.code].total + current.totalCost
      }
    };
  }, {})
);

Upvotes: 2

Nafis Islam
Nafis Islam

Reputation: 1509

const data = [
      {
        code: 'prod1',
        quantity: 13,
        pricePerItem: 10,
        totalCost: 130
      },
      {
        code: 'prod1',
        quantity: 7,
        pricePerItem: 11,
        totalCost: 77
      },
      {
        code: 'prod2',
        quantity: 10,
        pricePerItem: 9,
        totalCost: 90
      },
      {
        code: 'prod2',
        quantity: 9,
        pricePerItem: 10,
        totalCost: 90
      },
    ];

var result = 
    data.reduce(
      (acc, current) => {
        acc[current.code] = acc[current.code] || { quantity: 0, total: 0 };
        acc[current.code] = {
            total: acc[current.code].total + current.totalCost,
            quantity: acc[current.code].quantity + current.quantity,
        };
        return acc;
      },
      {}
    );

console.log(result);

Upvotes: 1

Md Sabbir Alam
Md Sabbir Alam

Reputation: 5054

You can use reduce to do the following,

const res = data.reduce((prev, curr) => {
   if(prev.hasOwnProperty(curr.code)) {
      prev[curr.code] = {total: prev[curr.code].total + curr.totalCost, quantity: prev[curr.code].quantity + curr.quantity };
      return prev;
   } else {
      prev[curr.code] = {total: curr.totalCost, quantity: curr.quantity };
      return prev;
   }
}, {});
console.log(res);

Upvotes: 2

Related Questions