23

Consider this JSON object below:

{
   "cells":[
      {
         "count":"1",
         "gdp_growth__avg":1.90575802503285,
         "geo__name":"united states of america",
         "time":1990
      },
      {
         "count":"1",
         "gdp_growth__avg":9.17893670154459,
         "geo__name":"china",
         "time":1991
      },
      {
         "count":"1",
         "gdp_growth__avg":-5.04693945214571,
         "geo__name":"russia",
         "time":1991
      },
      {
         "count":"1",
         "gdp_growth__avg":-0.0622142217811472,
         "geo__name":"botswana",
         "time":1991
      },
      {
         "count":"1",
         "gdp_growth__avg":14.2407063986337,
         "geo__name":"china",
         "time":1992
      },
      {
         "count":"1",
         "gdp_growth__avg":-14.5310737731921,
         "geo__name":"russia",
         "time":1992
      },
      {
         "count":"1",
         "gdp_growth__avg":3.55494453739944,
         "geo__name":"united states of america",
         "time":1992
      },
      {
         "count":"1",
         "gdp_growth__avg":13.9643147001603,
         "geo__name":"china",
         "time":1993
      },
      {
         "count":"1",
         "gdp_growth__avg":-8.66854034194856,
         "geo__name":"botswana",
         "time":1993
      },
      {
         "count":"1",
         "gdp_growth__avg":2.74204850437989,
         "geo__name":"united states of america",
         "time":1993
      },
      {
         "count":"1",
         "gdp_growth__avg":4.04272516401846,
         "geo__name":"united states of america",
         "time":1994
      },
      {
         "count":"1",
         "gdp_growth__avg":13.0806818010789,
         "geo__name":"china",
         "time":1994
      },
      {
         "count":"1",
         "gdp_growth__avg":-12.5697559787493,
         "geo__name":"russia",
         "time":1994
      },
      {
         "count":"1",
         "gdp_growth__avg":10.9249803004994,
         "geo__name":"china",
         "time":1995
      },
      {
         "count":"1",
         "gdp_growth__avg":-4.14352840666389,
         "geo__name":"russia",
         "time":1995
      },
      {
         "count":"1",
         "gdp_growth__avg":2.71655384149574,
         "geo__name":"united states of america",
         "time":1995
      },
      {
         "count":"1",
         "gdp_growth__avg":10.0085233990531,
         "geo__name":"china",
         "time":1996
      },
      {
         "count":"1",
         "gdp_growth__avg":3.79848988541973,
         "geo__name":"united states of america",
         "time":1996
      }
]
}

I would to Map and Reduce and generate a new object containing a summation of the GDP growth for all the countries in the above JSON that might look roughly like this:

{  
  {
     "gdp_growth__avg":46.23,
     "geo__name":"united states of america",
  },
  {
     "gdp_growth__avg":16.23,
     "geo__name":"china",
  },
  {
     "gdp_growth__avg":36.23,
     "geo__name":"russia",
  },
  {
     "gdp_growth__avg":26.23, 
     "geo__name":"botswana",
     "time":1991
  }
 }

I have looked at map and reduce and am not sure how best to proceed.

I was thinking something like this might be moving in the right directions, but does not seem to do what I was expecting:

      var arr = [{x:1},{x:2},{x:4}];

      arr.reduce(function (a, b) {
        return {x: a.x + b.x};
      });

      console.log(arr); //Outputs that same initial array

While I recognize that it is probably better and easier to do this on the server-side, I am wondering if what I am trying to do can be done on the client side with JavaScript. Any suggestions? Thanks in advance.

3
  • 5
    You want console.log(arr.reduce(…)). reduce does not alter the array (or even reassign the variable), it just returns a value. Commented Dec 1, 2015 at 0:05
  • @Bergi, +1 because i learned something here that i did not expect. Thank you. Commented Dec 1, 2015 at 0:32
  • map and reduce can be used server side too if you use node. Probably whatever your server can run can do it. Most convenient in js or python (are there python-based servers?) Commented Dec 1, 2015 at 1:12

5 Answers 5

14

Try this:

var data = { cells:[...] };

var r = data.cells.reduce(function(pv, cv) {
    if ( pv[cv.geo__name] ) {
        pv[cv.geo__name] += cv.gdp_growth__avg;
    } else {
        pv[cv.geo__name] = cv.gdp_growth__avg;
    }
    return pv;
}, {});

console.log(r);

Output example:

    { 
      'united states of america': 18.76051995774611,
      'china': 71.39814330096999,
      'russia': -36.291297610751,
      'botswana': -8.730754563729707 
   }
Sign up to request clarification or add additional context in comments.

Comments

4

The Array.reduce method doesn't change the array object, it returns the results in a new array.

2 Comments

No, it does not return a new array.
it depends on the type of accumulator we use, it can be json object or even a js Map ,but array.map() returns a new array
1

I tried to do with better time complexity:

let ans = [];
let map = new Map();
ques.cells.forEach(x => {
if(map[x.geo__name]){
map.set(x.geo__name, map[x.geo__name] + x.gdp_growth__avg);
}else{
map.set(x.geo__name,x.gdp_growth__avg);
}
});

map.forEach((v,k)=>{
ans.push({"geo__name":k, "gdp_growth__avg":v});
});
ques.cells = ans;

with solution looking like this:

[
  {
    "geo__name": "united states of america",
    "gdp_growth__avg": 3.79848988541973
  },
  {
    "geo__name": "china",
    "gdp_growth__avg": 10.0085233990531
  },
  {
    "geo__name": "russia",
    "gdp_growth__avg": -4.14352840666389
  },
  {
    "geo__name": "botswana",
    "gdp_growth__avg": -8.66854034194856
  }
]

Comments

1

You can try something like this:

var data = {"cells": [...]};

data.cells.map(function(datum) {
  return {
    geo__name: datum.geo__name,
    gdp_growth__avg: data.cells.filter(function(o) {
      return o.geo__name === datum.geo__name;
    }).reduce(function(sum, o) {
      return sum + o.gdp_growth__avg;
    }, 0)
  };
})

Needless to say, you can extract other properties from datum as well, such as time. I haven't.

Comments

1

To the solution given by @Hunan, I added https://stackoverflow.com/a/53294268/341117 to get result without duplicates

The final solution I used is :

var data = {"cells": [...]};

data =  data.cells.map(function(datum) {
  return {
    geo__name: datum.geo__name,
    gdp_growth__avg: data.cells.filter(function(o) {
      return o.geo__name === datum.geo__name;
    }).reduce(function(sum, o) {
      return sum + o.gdp_growth__avg;
    }, 0)
  };
}).filter((obj, pos, arr) => {
        return arr.map(mapObj =>
              mapObj.geo__name).indexOf(obj.geo__name) == pos;
        });

JS Fiddle - https://jsfiddle.net/8b4z3yc5/

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.