1

So I have a JSON file, that has some data for all the countries of the world. Each country is an array of objects. Each object in the array has a Date property, a confirmed property etc.

{
  "Afghanistan": [
    {
      "date": "2020-1-22",
      "confirmed": 5,
      "deaths": 0,
      "recovered": 0
    },
    {
      "date": "2020-1-23",
      "confirmed": 7,
      "deaths": 0,
      "recovered": 0
    }],
"Albania": [
    {
      "date": "2020-1-22",
      "confirmed": 3,
      "deaths": 0,
      "recovered": 0
    },
    {
      "date": "2020-1-23",
      "confirmed": 10,
      "deaths": 0,
      "recovered": 0
    }]
}

For the past few days, I am trying to find a way to create an array that will host the sum of all confirmed cases for each day.

So let's say we have 2 days, and our array will have 2 elements, on the first element I want to have the sum of confirmed for each country for 2020-1-22 and on the second element, the confirmed for each country for 2020-1-23. So the array should look something like that:

[8 , 17]

This is probably something easy to do, but it seems I can't wrap my head around it to find a solution. I've studied similar solutions using reduce and map methods, but when I try to apply to my case, my brain simply gets too perplexed.

7
  • would you post what you have tried so far? Commented Apr 16, 2020 at 13:40
  • I've been trying for several days with no real result. I've tried a lot of things, but I haven't posted one, because nothing came close to what I want to achieve, but I will add some of the code on the original post. Commented Apr 16, 2020 at 13:42
  • 1
    Search for "javascript array of objects group by property". You then only have to find a way how to combine the arrays of the different countries into one big array. Commented Apr 16, 2020 at 13:42
  • I am not able to get how are you getting [8 , 17] from the posted JSON data. Could you please elaborate. Commented Apr 16, 2020 at 13:45
  • 1
    " I've studied similar solutions using reduce and map methods, but when I try to apply to my case, my brain simply gets too perplexed." Post the code you just mentioned in your post as a minimal reproducible example. Commented Apr 16, 2020 at 13:51

3 Answers 3

3

You can do it using reduce and forEach. I also change the output format, instead of array I return an object.

const records = {Afghanistan: [{date: "2020-1-22",confirmed: 5,deaths: 0,recovered: 0},{date: "2020-1-23",confirmed: 7,deaths: 0,recovered: 0}],Albania: [{date: "2020-1-22",confirmed: 3,deaths: 0,recovered: 0},{date: "2020-1-23",confirmed: 10,deaths: 0,recovered: 0}]};

const res = Object.values(records).reduce((acc, curr) => {
    curr.forEach(item => {
	acc[item.date] = (acc[item.date] || 0) + item.confirmed;
    });
    return acc;
}, {})

console.log(res);

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

3 Comments

Add another Object.values() and you have the expected [8, 17]
I know but I think the object is better than the array. But I appreciate your response @Andreas
Thank you for your reply. This indeed does what I want to achieve. Instead of another Object.values() i used some .push to push the data to an array (since I need the data to be inside an array) and it seems to work as I want it to. I will study the code to understand how everything functions, since my goal is to learn.
1

This code will get you the key-value pairs of the dates and the values

const countries = {
  Afghanistan: [
    {
      date: "2020-1-22",
      confirmed: 5,
      deaths: 0,
      recovered: 0,
    },
    {
      date: "2020-1-23",
      confirmed: 7,
      deaths: 0,
      recovered: 0,
    },
  ],
  Albania: [
    {
      date: "2020-1-22",
      confirmed: 3,
      deaths: 0,
      recovered: 0,
    },
    {
      date: "2020-1-23",
      confirmed: 10,
      deaths: 0,
      recovered: 0,
    },
  ],
};

const objects = {};
const arrayOfResults = [];

for (const country in countries) {
  for (const data of countries[country]) {
    objects[data.date] = objects[data.date] + data.confirmed || data.confirmed;
  }
}

//currently we have a key-value pair of dates and total cases
// like this { '2020-1-22': 8, '2020-1-23': 17 }
// which in my opinion better represents the data

//get the results as an array in you case
for (const key in objects) {
  arrayOfResults.push(objects[key]);
}

Comments

1

You can get the values from your data object which will give you an array of your values:

[[{ "date": "2020-1-22", "confirmed": 5, "deaths": 0, "recovered": 0 }, { "date": "2020-1-23", "confirmed": 7, "deaths": 0, "recovered": 0 } ], ... ]

You can then use .reduce() on this array to accumulate to a new Map instance, where each key is the date and each value stored by the date is the amount total count/sum. To get these values, you'll need to loop through each object within the object values array, and convert grab the date and amount of confirmed cases for that particular object (here I do this via destructuring {date, [key]: amt}). You can then set the date value for the map to be the previously stored value (if present, if not use a 0) added with the current amount. You can then grab the .values() from the Map, and use Array.from() to convert the iterable to an array:

const data = { "Afghanistan": [{ "date": "2020-1-22", "confirmed": 5, "deaths": 0, "recovered": 0 }, { "date": "2020-1-23", "confirmed": 7, "deaths": 0, "recovered": 0 } ], "Albania": [{ "date": "2020-1-22", "confirmed": 3, "deaths": 0, "recovered": 0 }, { "date": "2020-1-23", "confirmed": 10, "deaths": 0, "recovered": 0 } ] };

const sumByKey = (key, data) =>
  Array.from(Object.values(data).reduce((map, objs) =>
    objs.reduce((m, {date, [key]: amt}) => m.set(date, (m.get(date) || 0) + amt), map), new Map).values()
  );

console.log(sumByKey('confirmed', data));

2 Comments

Thank you Nick. This indeed does exactly what I want to achieve. I will study the code in order to understand it, and try to learn from it.
@TheoKondak no worries ;)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.