Nicholas
Nicholas

Reputation: 3737

JavaScript - JSON object, grouping and multiplication of values

I have a JSON output called result:

{
  "status": "success",
  "data": [
    {"id": "39036", "name": "Steve", "product": "10", "count": "5", "cost": "4"},
    {"id": "39037", "name": "Steve", "product": "11", "count": "5", "cost": "7"},
    {"id": "39038", "name": "Steve", "product": "12", "count": "5", "cost": "2"},
    {"id": "39039", "name": "Steve", "product": "12", "count": "4", "cost": "2"},
    {"id": "39040", "name": "Steve", "product": "12", "count": "1", "cost": "2"}
  ]
}

I need the product number, the count, the cost and the total for each product number

I.e. for above, the output would be:

((product 10, count 5, cost 4, total 20),
(product 11, count 5, cost 7, total 35),
(product 12, count 10, cost 2, total 20))

I am not sure where to begin with this, does anyone have any guidance?

Upvotes: 3

Views: 968

Answers (2)

tevemadar
tevemadar

Reputation: 13225

As you mention you have tried to do it with loops, it may be worth showing how that could work.

var json=
'{\
  "status": "success",\
  "data": [\
    {"id": "39036", "name": "Steve", "product": "10", "count": "5", "cost": "4"},\
    {"id": "39037", "name": "Steve", "product": "11", "count": "5", "cost": "7"},\
    {"id": "39038", "name": "Steve", "product": "12", "count": "5", "cost": "2"},\
    {"id": "39039", "name": "Steve", "product": "12", "count": "4", "cost": "2"},\
    {"id": "39040", "name": "Steve", "product": "12", "count": "1", "cost": "2"}\
  ]\
}';
var data=JSON.parse(json).data;              // only the array

var result={};
for(var i=0;i<data.length;i++){
  var order=data[i];
  if(result[order.product]){                 // such product is in the result already
    result[order.product].count+=parseInt(order.count);
  }else{                                     // product is something new
    result[order.product]={
      product:order.product,
      count:parseInt(order.count),
      cost:parseInt(order.cost),
    }
  }
}

// put result in a list
var resultlist=[];
for(var product in result){
  result[product].total=result[product].cost*result[product].count;
  resultlist.push(result[product]);
}
console.log(resultlist);

And then comes reduce() as a shortcut.

Upvotes: 2

Nenad Vracar
Nenad Vracar

Reputation: 122077

You can use reduce method to create one object with values and then Object.values to get array of objects as a result.

const json = {"status" : "success", "data" : [{"id":"39036","name":"Steve","product":"10","count":"5","cost":"4"},{"id":"39037","name":"Steve","product":"11","count":"5","cost":"7"},{"id":"39038","name":"Steve","product":"12","count":"5","cost":"2"},{"id":"39039","name":"Steve","product":"12","count":"4","cost":"2"},{"id":"39040","name":"Steve","product":"12","count":"1","cost":"2"}] }

// Take { product, count, cost} from current element in reduce callback
const result = Object.values(json.data.reduce((r, { product, count, cost}) => {
  // Check if product exists in accumulator
  // If not set its value to a new object
  if (!r[product]) r[product] = { product, count, cost, total: count * cost}
  // If it does exists update count and total values
  // +count will convert string to number
  else {
    r[product].count = +r[product].count + +count;
    r[product].total = +r[product].count * +r[product].cost
  }
  return r;
}, {}))

console.log(result)

You could also use ES6 Map to store data and then use values() method with spread syntax to get array as a result.

const json = {"status" : "success", "data" : [{"id":"39036","name":"Steve","product":"10","count":"5","cost":"4"},{"id":"39037","name":"Steve","product":"11","count":"5","cost":"7"},{"id":"39038","name":"Steve","product":"12","count":"5","cost":"2"},{"id":"39039","name":"Steve","product":"12","count":"4","cost":"2"},{"id":"39040","name":"Steve","product":"12","count":"1","cost":"2"}] }

const map = json.data.reduce((r, {product,count,cost}) => {
  if (!r.has(product)) {
    r.set(product, { product, count, cost, total: count * cost})
  } else {
    const prod = r.get(product);
    prod.count = +prod.count + +count;
    prod.total = +prod.cost * +prod.count
  }
  return r;
}, new Map);

const result = [...map.values()]

console.log(result)

Upvotes: 3

Related Questions