Group by and calculate mean / average of properties in a Javascript array

后端 未结 7 817
臣服心动
臣服心动 2021-01-18 14:22

I struggled finding the solution I was looking for in other stackoverflow posts, even though I strongly feel as if it must exist. If it does, please do forward me in the rig

7条回答
  •  甜味超标
    2021-01-18 14:59

    You could take a dynamic approach by using a Map and generate all items after collecting the unknown keys.

    function groupBy(array, key) {
        return Array.from(
            array.reduce((m, o) => {
                var temp = m.get(o[key]);
                if (!temp) {
                    m.set(o[key], temp = {});
                }
                Object.entries(o).forEach(([k, v]) => {
                    if (k === key) {
                        return;
                    }
                    temp[k] = temp[k]  || { sum: 0, count: 0 };
                    temp[k].sum += v;
                    temp[k].count++;
                });
                return m;
            }, new Map),
            ([k, v]) => Object.assign({ [key]: k }, ...Object.entries(v).map(([l, { sum, count }]) => ({ [l]: +(sum / count).toFixed(1) })))
        );
    }
    
    const myData = [{ team: "GSW", pts: 120, ast: 18, reb: 11 }, { team: "GSW", pts: 125, ast: 28, reb: 18 }, { team: "GSW", pts: 110, ast: 35, reb: 47 }, { team: "HOU", pts: 100, ast: 17, reb: 43 }, { team: "HOU", pts: 102, ast: 14, reb: 32 }, { team: "SAS", pts: 127, ast: 21, reb: 25 }, { team: "SAS", pts: 135, ast: 25, reb: 37 }, { team: "SAS", pts: 142, ast: 18, reb: 27 }];
    
    console.log(groupBy(myData, 'team'));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    With rest properties (babel: true).

    function groupBy(array, key) {
        return Array.from(
            array.reduce((m, { [key]: k, ...rest}) => {
                var temp = m.get(k);
                if (!temp) {
                    m.set(k, temp = {});
                }
                Object.entries(rest).forEach(([l, v]) => {
                    temp[l] = temp[l]  || { sum: 0, count: 0 };
                    temp[l].sum += v;
                    temp[l].count++;
                });
                return m;
            }, new Map),
            ([k, v]) => Object.assign({ [key]: k }, ...Object.entries(v).map(([l, { sum, count }]) => ({ [l]: +(sum / count).toFixed(1) })))
        );
    }
    
    const myData = [{ team: "GSW", pts: 120, ast: 18, reb: 11 }, { team: "GSW", pts: 125, ast: 28, reb: 18 }, { team: "GSW", pts: 110, ast: 35, reb: 47 }, { team: "HOU", pts: 100, ast: 17, reb: 43 }, { team: "HOU", pts: 102, ast: 14, reb: 32 }, { team: "SAS", pts: 127, ast: 21, reb: 25 }, { team: "SAS", pts: 135, ast: 25, reb: 37 }, { team: "SAS", pts: 142, ast: 18, reb: 27 }];
    
    console.log(groupBy(myData, 'team'));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

提交回复
热议问题