如何用JavaScript实现数组多键组合分组并对count字段求和
问题:生成所有键组合的聚合统计结果
原始数据
const results = [ { make: "audi", fuel: "gasoline", model: "a1", count: 8 }, { make: "audi", fuel: "diesel", model: "a3", count: 2 }, { make: "audi", fuel: "gasoline", model: "a3", count: 5 } ];
目标结果
需要生成make、fuel、model所有可能的组合(包括部分键设为undefined的情况),并对count字段求和,最终得到如下结构:
const mappedResults = [ { make: "audi", fuel: undefined, model: undefined, count: 8 + 2 + 5 }, { make: "audi", fuel: "diesel", model: undefined, count: 2 }, { make: "audi", fuel: "gasoline", model: undefined, count: 8 + 5 }, { make: "audi", fuel: "gasoline", model: "a1", count: 8 }, { make: "audi", fuel: "diesel", model: "a3", count: 2 }, { make: "audi", fuel: "gasoline", model: "a3", count: 5 }, { make: "audi", fuel: undefined, model: "a1", count: 8 }, { make: "audi", fuel: undefined, model: "a3", count: 2 + 5 }, { make: undefined, fuel: undefined, model: "a1", count: 8 }, { make: undefined, fuel: undefined, model: "a3", count: 2 + 5 }, { make: undefined, fuel: "gasoline", model: "a1", count: 8 }, { make: undefined, fuel: "diesel", model: "a3", count: 2 }, { make: undefined, fuel: "gasoline", model: "a3", count: 5 }, { make: undefined, fuel: "gasoline", model: undefined, count: 8 + 5 }, { make: undefined, fuel: "diesel", model: undefined, count: 2 } ];
当前实现方式
我通过Lodash的groupBy、reduce等方法实现了需求,代码如下:
const groupedByMake = groupBy(results, "make"); const groupedByModel = groupBy(results, "model"); const groupedByFuel = groupBy(results, "fuel"); let groupedByMakeModel = {} results.reduce(function (r, o) { var key = o.make + "-" + o.model; if (!groupedByMakeModel[key]) { groupedByMakeModel[key] = Object.assign({}, o); // 创建对象副本 r.push(groupedByMakeModel[key]); } else { groupedByMakeModel[key].count += o.count; } return r; }, []); let groupedByMakeFuel = {} results.reduce(function (r, o) { var key = o.make + "-" + o.fuel; if (!groupedByMakeFuel[key]) { groupedByMakeFuel[key] = Object.assign({}, o); // 创建对象副本 r.push(groupedByMakeFuel[key]); } else { groupedByMakeFuel[key].count += o.count; } return r; }, []); let groupedByModelFuel = {} results.reduce(function (r, o) { var key = o.model + "-" + o.fuel; if (!groupedByModelFuel[key]) { groupedByModelFuel[key] = Object.assign({}, o); // 创建对象副本 r.push(groupedByModelFuel[key]); } else { groupedByModelFuel[key].count += o.count; } return r; }, []); let groupedByMakeModelFuel = {} results.reduce(function (r, o) { var key = o.make + "-" + o.model + "-" + o.fuel; if (!groupedByMakeModelFuel[key]) { groupedByMakeModelFuel[key] = Object.assign({}, o); // 创建对象副本 r.push(groupedByMakeModelFuel[key]); } else { groupedByMakeModelFuel[key].count += o.count; } return r; }, []); const result = [] each(keys(groupedByMake), key => { return result.push({ make: key, model: undefined, fuel: undefined, count: sumBy(groupedByMake[key], 'count') }) }) each(keys(groupedByModel), key => { return result.push({ make: undefined, model: key, fuel: undefined, count: sumBy(groupedByModel[key], 'count') }) }) each(keys(groupedByFuel), key => { return result.push({ make: undefined, model: undefined, fuel: key, count: sumBy(groupedByFuel[key], 'count') }) }) each(keys(groupedByMakeModel), key => { return result.push({ make: groupedByMakeModel[key]?.make, model: groupedByMakeModel[key]?.model, fuel: undefined, count: groupedByMakeModel[key]?.count }) }) each(keys(groupedByMakeFuel), key => { return result.push({ make: groupedByMakeFuel[key]?.make, model: undefined, fuel: groupedByMakeFuel[key]?.fuel, count: groupedByMakeFuel[key]?.count }) }) each(keys(groupedByModelFuel), key => { return result.push({ make: undefined, model: groupedByModelFuel[key]?.model, fuel: groupedByModelFuel[key]?.fuel, count: groupedByModelFuel[key]?.count }) }) each(keys(groupedByMakeModelFuel), key => { return result.push({ make: groupedByMakeModelFuel[key]?.make, model: groupedByMakeModelFuel[key]?.model, fuel: groupedByMakeModelFuel[key]?.fuel, count: groupedByMakeModelFuel[key]?.count }) }) console.log("result: ", result)
疑问
有没有更优、更高效的实现方式?
内容的提问来源于stack exchange,提问作者Boky
相关产品推荐
相关产品推荐

