0

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"
  }
]

3 Answers 3

4

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 }

Sign up to request clarification or add additional context in comments.

3 Comments

But, I don't know it's year or month. It should be based on cols array. So, I should iterate over cols before reduce?
Because if I do that it's not working: newObject = Object.values( cols.forEach(col => { dataArray.reduce((acc, { col, ...rest }) => { console.log(col); return acc }); }, {}) )
@ketan it wasn't really clear from your question what you wanted, so I wrote an answer based on the data in the question. I think I understand better now, and I've updated my answer to group based on the cols array and sum the values based on the keys in the keys array that are not also in the cols array. Please see my edit...
1

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)

Comments

0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.