tharindu
tharindu

Reputation: 523

Iterate through a groupby array of json

I have an array of JSON object as follows

 var array = [{"id":"1","value": "13"},{"id":"2","value": "23"},{"id":"1","value": "33"},{"id":"3","value": "13"}]

Then I grouped the json array according to the id as follows

var groupArray = {"1":[{"id":"1","value": "13"},{"id":"1","value": "33"}],
                     "2": [{"id":"2","value": "23"}],
                     "3": [{"id":"3","value": "13"}]};

I want to iterate through groupArray and get the total of value for each id where duplicate ids should sum up together and give one single total value and assign them into another array as follows

resultArray
[{"id":"1","value":"46"},{"id":"2","value":"23"},{"id":"3","value":"13"}]

This should be achieved using angularjs

Upvotes: 2

Views: 3627

Answers (4)

Ele
Ele

Reputation: 33726

You can use the function reduce for grouping and the function Object.values for extracting the desired output.

var array = [{"id":"1","value": "13"},{"id":"2","value": "23"},{"id":"1","value": "33"},{"id":"3","value": "13"}]
let result = Object.values(array.reduce((a, {id, value}) => {
  (a[id] || (a[id] = {id, value: 0})).value += +value;
  return a;
}, Object.create(null)));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

holydragon
holydragon

Reputation: 6728

Use Object.entries to get the object keys and values as an array then iterate through the values in order to sum up the value inside each object and then push it with its id to resultArray.

let groupArray = {"1":[{"id":"1","value": "13"},{"id":"1","value": "33"}],"2": [{"id":"2","value": "23"}],"3": [{"id":"3","value": "13"}]}
let resultArray = []
Object.entries(groupArray).forEach(g => {
  let sumValue = 0
  g[1].forEach(o => sumValue += parseFloat(o.value))
  resultArray.push({
    "id": g[0],
    "value": sumValue.toString()
  })
})
console.log(resultArray)

Upvotes: 0

Mark
Mark

Reputation: 92440

It would be easier if groupArray was in fact an array. As an object you have to be aware that order has not always been guaranteed, but it's not clear if the order of your final array is important. In recent JS it shouldn't matter — numeric keys will be sorted. You can just call map() on the Object.values(), then use reduce() on each array:

var groupArray = {
    "1":[{"id":"1","value": "13"},{"id":"1","value": "33"}],
    "2": [{"id":"2","value": "23"}],
    "3": [{"id":"3","value": "13"}]
}

let sums = Object.values(groupArray)
           .map(arr => arr.reduce((sums,{id, value}) => ({id, value: sums.value + +value}), {value:0}))
console.log(sums)

You need to be aware that value is a string and make sure you are adding numbers not concatenating strings when you use +.

Upvotes: 1

Takahiro Ito
Takahiro Ito

Reputation: 56

This will work

const object = {}
const array = [{"id":"1","value": "13"},{"id":"2","value": "23"},{"id":"1","value": "33"},{"id":"3","value": "13"}]

array.forEach(data => {
  object[data.id] = parseInt(data.value, 10) + (object[data.id] || 0)
})

const result = Object.entries(object).map(data => {
  return {
    'id': data[0],
    'value': data[1]
  }
})

console.log(result)

Upvotes: 0

Related Questions