-2

I have an array of objects:

var obj = [
  {name: 'a1', type: 't1', price: 10},
  {name: 'a1', type: 't1', price: 10},
  {name: 'a2', type: 't2', price: 10},
  {name: 'a1', type: 't2', price: 10},
];

I need to get this result:

[
  {name: 'a1', type: 't1', price: 20},
  {name: 'a1', type: 't2', price: 10},
  {name: 'a2', type: 't2', price: 10}
]

I want to sum the item if, and only if, the properties name and type match. Any idea?

fubar
  • 16,918
  • 4
  • 37
  • 43
muimui
  • 1
  • 1
  • Read your question and make us understand in the comments, – Harish Soni May 17 '18 at 06:57
  • 2
    Possible duplicate [What is the most efficient method to groupby on a JavaScript array of objects?](https://stackoverflow.com/questions/14446511/what-is-the-most-efficient-method-to-groupby-on-a-javascript-array-of-objects) – Dean May 17 '18 at 06:57
  • @HarishSoni never mind the question, i just need to get the result though – muimui May 17 '18 at 06:59
  • Where are you having difficulties? – fubar May 17 '18 at 06:59
  • When people doesn't understand your question, how people give you the result. – Dean May 17 '18 at 06:59
  • Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. – baao May 17 '18 at 07:01
  • make an array with key of name|type and add the price. if needed you can split it up again afterwards . – Domenik Reitzner May 17 '18 at 07:04
  • @Dean ok i want to get the sum of the price if both the 'name' and 'type' is the same. is that clear enough? thanks :) – muimui May 17 '18 at 07:05

4 Answers4

3

You can use reduce to group it into an object. Use Object.values to convert the object into array.

var obj = [
    {name: 'a1', type: 't1', price: 10},
    {name: 'a1', type: 't1', price: 10},
    {name: 'a2', type: 't2', price: 10},
    {name: 'a1', type: 't2', price: 10},
];

var result = Object.values(obj.reduce((c, v) => {
  let k = v.name + '-' + v.type;
  c[k] = c[k] || {...v, price: 0};
  c[k].price += v.price;
  return c;
}, {}));

console.log(result);
Eddie
  • 26,593
  • 6
  • 36
  • 58
0

You could reduce into a Map and turn it back into an array:

var obj = [
 {name: 'a1', type: 't1', price: 10},
 {name: 'a1', type: 't1', price: 10},
 {name: 'a2', type: 't2', price: 10},
 {name: 'a1', type: 't2', price: 10},
];

const map = obj.reduce((map, { name, type, price }) => {
  console.log('iter');
  const key = name + '_' + type;
  return map.set(key, (map.get(key) || 0) + price);
}, new Map());

const output = [...map.entries()].map(([key, val]) => {
  const [name, type] = key.split('_');
  return { name, type, price: val };
});
console.log(output);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
0

You can try following (sum and sort by name and type)

var obj = [
 {name: 'a1', type: 't1', price: 10},
 {name: 'a1', type: 't1', price: 10},
 {name: 'a2', type: 't2', price: 10},
 {name: 'a1', type: 't2', price: 10},
];

// First create the result object where sum of price is done
var result =  obj.reduce((a,c) => {
  if(a[c.name + "_" + c.type]) {
    a[c.name + "_" + c.type].price += c.price;
  } else {
    a[c.name + "_" + c.type] = c;
  }
  return a;
}, {});

// Get the values in an array
result = Object.values(result);

// Sort the array by name and then type
result.sort((a,b) => {
  if(a.name === b.name) return a.type.localeCompare(b.type);
  return a.name.localeCompare(b.name);
});

console.log(result);
Nikhil Aggarwal
  • 28,197
  • 4
  • 43
  • 59
0

You can use of Array.reduce to build up a new array considering your requirements.

const obj = [{
    name: 'a1',
    type: 't1',
    price: 10,
  },
  {
    name: 'a1',
    type: 't1',
    price: 10,
  },
  {
    name: 'a2',
    type: 't2',
    price: 10,
  },
  {
    name: 'a1',
    type: 't2',
    price: 10,
  },
].reduce((tmp, x) => {
  // Look if there is already a matching item in tmp
  const findItem = tmp.find(y => y.name === x.name && y.type === x.type);

  // It's not inside
  if (!findItem) {
    tmp.push(x);

    return tmp;
  }

  // it is inside
  findItem.price += x.price;

  return tmp;
}, []);

console.log(obj);
Orelsanpls
  • 22,456
  • 6
  • 42
  • 69