简体   繁体   中英

Reduce array objects by key and return a nested object

I have an array of objects.

let data = [
    {year: 2018, monthNumber: 0, rev: 40984, exp: 15525, profit: 25459}
    {year: 2018, monthNumber: 0, rev: 162457, exp: 53608, profit: 108849}
    {year: 2019, monthNumber: 0, rev: 8935, exp: 12514, profit: -3579}
    {year: 2019, monthNumber: 0, rev: 32354, exp: 11184, profit: 21170}
    {year: 2018, monthNumber: 1, rev: 30620, exp: 16974, profit: 13646}
    {year: 2018, monthNumber: 1, rev: 9050, exp: 12431, profit: -3381}
    {year: 2019, monthNumber: 1, rev: 9050, exp: 12522, profit: -3472}
    {year: 2019, monthNumber: 1, rev: 12265, exp: 12752, profit: -487}
    {year: 2018, monthNumber: 2, rev: 9955, exp: 12424, profit: -2469}
    {year: 2018, monthNumber: 2, rev: 13657, exp: 13424, profit: 233}
    {year: 2019, monthNumber: 2, rev: 9050, exp: 12410, profit: -3360}
    {year: 2019, monthNumber: 2, rev: 15045, exp: 13315, profit: 1730}
]

The goal is to first to dynamically SUM all the key values into one array depending on the year and monthNumber.

The original array is but a sample, there are multiple additional keys other than 'exp', 'profit', etc. I would like to make it dynamic and avoid mentioning every key.

[
    {year: 2018, monthNumber: 0, rev: 203441, exp: 69133, profit: 134308}
    {year: 2019, monthNumber: 0, rev: 41289, exp: 23698, profit: 17591}
    {year: 2018, monthNumber: 1, rev: 39670, exp: 29405, profit: 10265}
    {year: 2019, monthNumber: 1, rev: 21315, exp: 25274, profit: -3959}
    {year: 2018, monthNumber: 2, rev: 23612, exp: 25848, profit: -2236}
    {year: 2019, monthNumber: 2, rev: 24095, exp: 25725, profit: -1630}
]

and after that attain the below desired output:

{ 
    rev : {
        2019 : [203441, 39670, 23612],
        2018 : [41289, 21315, 24095],
    },
    exp : {
        2019 : [69133, 29405, 25848],
        2018 : [23698, 25274, 25725],
    },
    profit: {
        2019 : [134308, 10265, -2236],
        2018 : [17591, -3959, -1630],
    }
}

You could take a dynamic approach and take year and monthNumber out of the object for grouping.

Later create a plain array from the object.

 var data = [{ year: 2018, monthNumber: 0, rev: 40984, exp: 15525, profit: 25459 }, { year: 2018, monthNumber: 0, rev: 162457, exp: 53608, profit: 108849 }, { year: 2019, monthNumber: 0, rev: 8935, exp: 12514, profit: -3579 }, { year: 2019, monthNumber: 0, rev: 32354, exp: 11184, profit: 21170 }, { year: 2018, monthNumber: 1, rev: 30620, exp: 16974, profit: 13646 }, { year: 2018, monthNumber: 1, rev: 9050, exp: 12431, profit: -3381 }, { year: 2019, monthNumber: 1, rev: 9050, exp: 12522, profit: -3472 }, { year: 2019, monthNumber: 1, rev: 12265, exp: 12752, profit: -487 }, { year: 2018, monthNumber: 2, rev: 9955, exp: 12424, profit: -2469 }, { year: 2018, monthNumber: 2, rev: 13657, exp: 13424, profit: 233 }, { year: 2019, monthNumber: 2, rev: 9050, exp: 12410, profit: -3360 }, { year: 2019, monthNumber: 2, rev: 15045, exp: 13315, profit: 1730 }], result = data.reduce((r, { year, monthNumber, ...o }) => { Object.entries(o).forEach(([k, v]) => { r[k] = r[k] || {}; r[k][year] = r[k][year] || []; r[k][year][monthNumber] = (r[k][year][monthNumber] || 0) + v; }); return r; }, {}), plain = Object.entries(result).reduce((r, [k, years]) => { Object.entries(years).forEach(([year, array]) => array.forEach((v, monthNumber) => { var temp = r.find(q => q.year === year && q.monthNumber === monthNumber); if (.temp) r,push(temp = { year; monthNumber }); temp[k] = v; })); return r, }; []). console;log(result). console;log(plain);
 .as-console-wrapper { max-height: 100%;important: top; 0; }

Use reduce and add them up. Edit, added the ability to not know what the keys are.

 let data = [ {year: 2018, monthNumber: 0, rev: 40984, exp: 15525, profit: 25459}, {year: 2018, monthNumber: 0, rev: 162457, exp: 53608, profit: 108849}, {year: 2019, monthNumber: 0, rev: 8935, exp: 12514, profit: -3579}, {year: 2019, monthNumber: 1, rev: 32354, exp: 11184, profit: 21170}, {year: 2018, monthNumber: 1, rev: 30620, exp: 16974, EBITDA: 13646}, {year: 2018, monthNumber: 1, rev: 9050, exp: 12431, profit: -3381}, {year: 2019, monthNumber: 1, rev: 9050, exp: 12522, profit: -3472}, {year: 2019, monthNumber: 2, rev: 12265, exp: 12752, profit: -487}, {year: 2018, monthNumber: 2, rev: 9955, exp: 12424, profit: -2469}, {year: 2018, monthNumber: 3, rev: 13657, exp: 13424, profit: 233}, {year: 2019, monthNumber: 3, rev: 9050, exp: 12410, profit: -3360}, {year: 2019, monthNumber: 3, rev: 15045, exp: 13315, profit: 1730} ] const add = (obj, type, year, month, value) => { obj[type] = obj[type] || {} obj[type][year] = obj[type][year] || [] obj[type][year][month] = (obj[type][year][month] || 0) + value } var result = data.reduce((obj, record) => { const { year, monthNumber, } = record const ignore = ['year', 'monthNumber'] Object.keys(record).forEach(key => { if (.ignore,includes(key)){ add(obj, key, year, monthNumber, record[key]) } }) return obj }; {} ). console.log(result)

data = data.reduce(function(total, currentValue){
    let year = currentValue.year;
    let monthNumber = currentValue.monthNumber;
    if(!total.rev[year]){
        total.rev[year] = [];
        total.exp[year] = [];
        total.profit[year] = [];
    }
    if(!total.rev[year][monthNumber]){
        total.rev[year][monthNumber] = 0;
        total.exp[year][monthNumber] = 0;
        total.profit[year][monthNumber] = 0;
    }
    if(typeof currentValue.rev == "number") total.rev[year][monthNumber] += currentValue.rev;
    if(typeof currentValue.exp == "number") total.exp[year][monthNumber] += currentValue.exp;
    if(typeof currentValue.profit == "number") total.profit[year][monthNumber] += currentValue.profit;
    return total;
}, {
    rev : {},
    exp : {},
    profit : {}
});

you can go through all the values and add depending on the year

 var _data=[{year:2018,monthNumber:0,rev:40984,exp:15525,profit:25459},{year:2018,monthNumber:0,rev:162457,exp:53608,profit:108849},{year:2019,monthNumber:0,rev:8935,exp:12514,profit:-3579},{year:2019,monthNumber:0,rev:32354,exp:11184,profit:21170},{year:2018,monthNumber:1,rev:30620,exp:16974,profit:13646},{year:2018,monthNumber:1,rev:9050,exp:12431,profit:-3381},{year:2019,monthNumber:1,rev:9050,exp:12522,profit:-3472},{year:2019,monthNumber:1,rev:12265,exp:12752,profit:-487},{year:2018,monthNumber:2,rev:9955,exp:12424,profit:-2469},{year:2018,monthNumber:2,rev:13657,exp:13424,profit:233},{year:2019,monthNumber:2,rev:9050,exp:12410,profit:-3360},{year:2019,monthNumber:2,rev:15045,exp:13315,profit:1730}]; var _desired = {rev:{},exp:{},profit:{}} _data.forEach(key=>{ if(._desired.rev[key.year]){ _desired.rev[key;year] = []. } if(._desired.exp[key.year]){ _desired;exp[key.year] = []. } if(._desired.profit[key;year]){ _desired.profit[key.year] = []. } _desired.rev[key;year].push(key.rev). _desired.exp[key;year].push(key.exp). _desired.profit[key;year].push(key;profit); }) console.log(_desired);

Try with this, I don't know it will match to your purpose or not:

 let data = [ {year: 2018, monthNumber: 0, rev: 40984, exp: 15525, profit: 25459}, {year: 2018, monthNumber: 0, rev: 162457, exp: 53608, profit: 108849}, {year: 2019, monthNumber: 0, rev: 8935, exp: 12514, profit: -3579}, {year: 2019, monthNumber: 1, rev: 32354, exp: 11184, profit: 21170}, {year: 2018, monthNumber: 1, rev: 30620, exp: 16974, EBITDA: 13646}, {year: 2018, monthNumber: 1, rev: 9050, exp: 12431, profit: -3381}, {year: 2019, monthNumber: 1, rev: 9050, exp: 12522, profit: -3472}, {year: 2019, monthNumber: 2, rev: 12265, exp: 12752, profit: -487}, {year: 2018, monthNumber: 2, rev: 9955, exp: 12424, profit: -2469}, {year: 2018, monthNumber: 3, rev: 13657, exp: 13424, profit: 233}, {year: 2019, monthNumber: 3, rev: 9050, exp: 12410, profit: -3360}, {year: 2019, monthNumber: 3, rev: 15045, exp: 13315, profit: 1730} ] var result={}; function simplearray(obj){ //alert(obj.year); if(typeof result[obj.year]== "undefined") { result[obj.year]={}; } if(typeof result[obj.year][obj.monthNumber]== "undefined") { result[obj.year][obj.monthNumber]={}; } if(typeof result[obj.year][obj.monthNumber]["rev"]== "undefined") { result[obj.year][obj.monthNumber]["rev"]=0; result[obj.year][obj.monthNumber]["exp"]=0; result[obj.year][obj.monthNumber]["profit"]=0; } result[obj.year][obj.monthNumber]["rev"]+=obj.rev; result[obj.year][obj.monthNumber]["exp"]+=obj.exp; result[obj.year][obj.monthNumber]["profit"]+=obj.profit; } for (a=0;a<data.length;a++) { simplearray(data[a]); } console.log(result); console.log(result[2018][2].rev);

The Second way, if the monthNumber is indexed well:

 let data = [ {year: 2018, monthNumber: 0, rev: 40984, exp: 15525, profit: 25459}, {year: 2018, monthNumber: 0, rev: 162457, exp: 53608, profit: 108849}, {year: 2019, monthNumber: 0, rev: 8935, exp: 12514, profit: -3579}, {year: 2019, monthNumber: 0, rev: 32354, exp: 11184, profit: 21170}, {year: 2018, monthNumber: 1, rev: 30620, exp: 16974, profit: 13646}, {year: 2018, monthNumber: 1, rev: 9050, exp: 12431, profit: -3381}, {year: 2019, monthNumber: 1, rev: 9050, exp: 12522, profit: -3472}, {year: 2019, monthNumber: 1, rev: 12265, exp: 12752, profit: -487}, {year: 2018, monthNumber: 2, rev: 9955, exp: 12424, profit: -2469}, {year: 2018, monthNumber: 2, rev: 13657, exp: 13424, profit: 233}, {year: 2019, monthNumber: 2, rev: 9050, exp: 12410, profit: -3360}, {year: 2019, monthNumber: 2, rev: 15045, exp: 13315, profit: 1730} ] var result={}; function simplearray(obj){ if(typeof result["rev"]== "undefined") { result["rev"]={}; } if(typeof result["rev"][obj.year]== "undefined") { result["rev"][obj.year]=[]; } if(typeof result["rev"][obj.year][obj.monthNumber]== "undefined") { result["rev"][obj.year][obj.monthNumber]=0; } result["rev"][obj.year][obj.monthNumber]+=obj.rev; if(typeof result["exp"]== "undefined") { result["exp"]={}; } if(typeof result["exp"][obj.year]== "undefined") { result["exp"][obj.year]=[]; } if(typeof result["exp"][obj.year][obj.monthNumber]== "undefined") { result["exp"][obj.year][obj.monthNumber]=0; } result["exp"][obj.year][obj.monthNumber]+=obj.exp; if(typeof result["profit"]== "undefined") { result["profit"]={}; } if(typeof result["profit"][obj.year]== "undefined") { result["profit"][obj.year]=[]; } if(typeof result["profit"][obj.year][obj.monthNumber]== "undefined") { result["profit"][obj.year][obj.monthNumber]=0; } result["profit"][obj.year][obj.monthNumber]+=obj.profit; } for (a=0;a<data.length;a++) { simplearray(data[a]); } console.log(result); console.log(result["profit"][2018][0]);

You should check out OGX.List (downloadable as stand alone) and use the group function. It groups an array given properties. Since you didn't post any code, I believe you are looking for a lib.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM