Reputation: 19341
I am trying to create new array of object with total data by year(or any selected key) but, it doesn't work as expected.
const dataArray = [
{
"abc": 10,
"xyz": 20,
"year": "2021"
},
{
"abc": 20,
"xyz": 20,
"year": "2022"
},
{
"abc": 20,
"xyz": 10,
"year": "2021"
},
{
"abc": 30,
"xyz": 10,
"year": "2022"
},
{
"abc": 20,
"xyz": 10,
"year": "2021"
},
{
"abc": 10,
"xyz": 10,
"year": "2022"
}
]
const keys = ["year", "abc", "xyz"];
const cols = ["year"]
//expected
//[{ "abc": total of abc for 2021, "xyz": total of xyz for 2021, "year" "2021"}, { "abc": total of abc for 2022, "xyz": total of xyz for 2022, "year" "2022"}]
const newObject = {};
cols.forEach(col => {
dataArray.forEach(arr => {
keys.forEach(key => {
if(col != key) {
newObject[key] += col[key]
}
})
})
})
console.log(newObject);
I tried above but doesn't work as expected.
My expectation is:
[
{
"abc": "total of abc for 2021",
"xyz": "total of xyz for 2021",
"year": "2021"
},
{
"abc": "total of abc for 2022",
"xyz": "total of xyz for 2022",
"year": "2022"
}
]
Upvotes: 0
Views: 64
Reputation: 1681
const dataArray = [
{
"abc": 10,
"xyz": 20,
"year": "2021"
},
{
"abc": 20,
"xyz": 20,
"year": "2022"
},
{
"abc": 20,
"xyz": 10,
"year": "2021"
},
{
"abc": 30,
"xyz": 10,
"year": "2022"
},
{
"abc": 20,
"xyz": 10,
"year": "2021"
},
{
"abc": 10,
"xyz": 10,
"year": "2022"
}
]
const result = dataArray.reduce((res, ele) => {
let exist = res.find(e => e.year === ele.year)
if(exist) {
exist.abc += ele.abc
exist.xyz += ele.xyz
} else {
res = [...res, {...ele}]
}
return res
}, [])
// other way
const result1 = Object.values(
dataArray.reduce((res, {year, ...rest}) => {
let ele = res[year] ??= {year}
Object.entries(rest).forEach(([k, v]) => ele[k] = (ele[k] ?? 0) + v)
return res
}, {})
)
console.log(result, result1)
Upvotes: 1
Reputation: 146
if you want some different approach
const dataArray = [
{
"abc": 10,
"xyz": 20,
"year": "2021"
},
{
"abc": 20,
"xyz": 20,
"year": "2022"
},
{
"abc": 20,
"xyz": 10,
"year": "2021"
},
{
"abc": 30,
"xyz": 10,
"year": "2022"
},
{
"abc": 20,
"xyz": 10,
"year": "2021"
},
{
"abc": 10,
"xyz": 10,
"year": "2022"
}
]
let mainObj = {}
dataArray.forEach((el)=>{
if(!mainObj.hasOwnProperty(el.year)){
mainObj[el.year] = {}
mainObj[el.year].abc = el.abc
mainObj[el.year].xyz = el.xyz
mainObj[el.year].year = el.year
}
else{
mainObj[el.year].abc = mainObj[el.year].abc + el.abc
mainObj[el.year].xyz = mainObj[el.year].xyz + el.xyz
}
})
let values = Object.values(mainObj)
console.log(values)
Upvotes: 0
Reputation: 147266
You can aggregate dataArray
using reduce
, building an object whose keys are the year
values and values are the accumulated abc
and xyz
values. You can then convert that into your desired array format using Object.values
:
const dataArray = [{
"abc": 10, "xyz": 20, "year": "2021"
},
{
"abc": 20, "xyz": 20, "year": "2022"
},
{
"abc": 20, "xyz": 10, "year": "2021"
},
{
"abc": 30, "xyz": 10, "year": "2022"
},
{
"abc": 20, "xyz": 10, "year": "2021"
},
{
"abc": 10, "xyz": 10, "year": "2022"
}
]
const keys = ["year", "abc", "xyz"];
const cols = ["year"]
newObject = Object.values(
dataArray.reduce((acc, obj) => {
colkey = cols.map(k => obj[k]).join('##')
if (acc.hasOwnProperty(colkey)) {
keys.filter(k => !cols.includes(k)).forEach(k => acc[colkey][k] += obj[k])
} else {
acc[colkey] = obj
}
return acc
}, {})
);
console.log(newObject);
.as-console-wrapper { max-height: 100% !important }
Upvotes: 4