[英]Map and Reduce JSON Objects with JavaScript
Consider this JSON object below:考虑下面的 JSON object:
{
"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:我将对 Map 和 Reduce 生成一个新的 object,其中包含上述 JSON 中所有国家/地区的 GDP 增长总和,大致如下所示:
{
{
"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.我查看了map并减少了,但不确定如何最好地进行。
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?虽然我认识到在服务器端执行此操作可能更好、更容易,但我想知道我正在尝试做的事情是否可以在客户端使用 JavaScript 完成。有什么建议吗? Thanks in advance.
提前致谢。
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
}
Array.reduce
方法不会更改数组对象,而是以新数组的形式返回结果。
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
.不用说,您也可以从
datum
提取其他属性,例如time
。 I haven't.我没有。
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
}
]
To the solution given by @Hunan, I added https://stackoverflow.com/a/53294268/341117 to get result without duplicates对于@Hunan 给出的解决方案,我添加了https://stackoverflow.com/a/53294268/341117以获得没有重复的结果
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/ JS 小提琴 - https://jsfiddle.net/8b4z3yc5/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.