5

I have an array of js objects which look like this:

var objArr = [
     {"Country": "US", "City": "MyCity1", "2017-07-12": "1", "2017-07-13": "2"},
     {"Country": "US", "City": "MyCity2", "2017-07-12": "2", "2017-07-13": "2"},
     {"Country": "CN", "City": "MyCity1", "2017-07-12": "5", "2017-07-13": "7"},
     {"Country": "CN", "City": "MyCity2", "2017-07-12": "5", "2017-07-13": "7"}
   ]

I wanna create a new array where the country is unique, but also the dates should be summed.

{"Country": "US", "2017-07-12":  "3", "2017-07-13": "4"},
{"Country": "CN", "2017-07-12": "10", "2017-07-13": "14"}
            ^^^^                ^^^^                ^^^^   

I have problems getting my head around it. Do I have to filter first, reduce it somehow, remap it,... I've no idea to start? Any help would be appreciated, thank you!

3
  • Oh, in that case you just need to group the entries by country and then sum the values of the same properties Commented Mar 2, 2020 at 15:02
  • Does this answer your question? Most efficient method to groupby on an array of objects Commented Mar 2, 2020 at 15:06
  • In particular, you can have a look at Scott Sauyet's answer which provides a more flexible approach. Some others also show how you can group and transform. Commented Mar 2, 2020 at 15:08

3 Answers 3

3

Use Array.reduce, check if an object with the current country exists, if it does, loop through the Object.keys to update the values, if not, push a new one :

EDIT : If you don't want City you can destructure it {City, ...curr}

var objArr = [
  { Country: "US", City: "MyCity1", "2017-07-12": "1", "2017-07-13": "2" },
  { Country: "US", City: "MyCity2", "2017-07-12": "2", "2017-07-13": "2" },
  { Country: "CN", City: "MyCity1", "2017-07-12": "5", "2017-07-13": "7" },
  { Country: "CN", City: "MyCity2", "2017-07-12": "5", "2017-07-13": "7" }
];

var result = objArr.reduce((acc, {City, ...curr}) => {
  const ndx = acc.findIndex(e => e.Country === curr.Country);
  if (ndx > -1) {
    const [country, ...keys] = Object.keys(curr);
    keys.forEach(k => {
      acc[ndx][k] = +acc[ndx][k] + +curr[k];
    });
  } else {
    acc.push(curr);
  }
  return acc;
}, []);

console.log(result);

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

1 Comment

Op don't want city in result
0

Use one forEach for array and go over each object date keys using forEach and build the one res object with unique keys as Country and accumulated values. Use Object.values of res to get the array from res object.

Update: Fix to make sure always one type for dates which is number.

var objArr = [
  { Country: "US", City: "MyCity1", "2017-07-12": "1", "2017-07-13": "2" },
  { Country: "US", City: "MyCity2", "2017-07-12": "2", "2017-07-13": "2" },
  { Country: "CN", City: "MyCity1", "2017-07-12": "5", "2017-07-13": "7" },
  { Country: "CN", City: "MyCity2", "2017-07-12": "5", "2017-07-13": "7" }
];

const update = data => {
  const res = {};
  data.forEach(({ Country, City, ...dates }) => {
    const item = res[Country] || { Country };
    Object.keys(dates).forEach(date => {
      item[date] = (item[date] || 0) + Number(dates[date]);
    });
    res[Country] = { ...item };
  });
  return Object.values(res);
};

console.log(update(objArr));

2 Comments

im some of my results the values are strings, and some are integers. Is this normal? ` Country: "China" 3/1/20: 79826 3/2/20: 80026 1: Country: "Thailand" 1/22/20: "2" 1/23/20: "3"
@Jan, Oh I see. I think its better to have same type for items. Here I think number is better. I updated answer to make sure always have number.
0

You can use reduce() to create an object to group elements and then use Object.values

var objArr = [
     {"Country": "US", "City": "MyCity1", "2017-07-12": "1", "2017-07-13": "2"},
     {"Country": "US", "City": "MyCity2", "2017-07-12": "2", "2017-07-13": "2"},
     {"Country": "CN", "City": "MyCity1", "2017-07-12": "5", "2017-07-13": "7"},
     {"Country": "CN", "City": "MyCity2", "2017-07-12": "5", "2017-07-13": "7"}
   ]

let keys = ["2017-07-12", "2017-07-13"];
const res = Object.values(objArr.reduce((ac, a) => {
  if(!ac[a.Country]){
    ac[a.Country] = {Country: a.Country};
  }

  keys.forEach(k => {
    ac[a.Country][k] = (ac[a.Country][k] || 0) + Number(a[k]);
  })
  return ac;
}, {}))
console.log(res)

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.