经过一些研究,我发现了这个解决方案:
https://gist.github.com/guillaumegarcia13/668518119667594fdca150ebefecd194
下面的原型支持嵌套属性和可选回调参数,以计算对元素的某些操作。
/**
* GroupBy array extension
*/
interface Grouping<T> {
key: string,
values: Array<T>,
computed: any
}
interface Array<T> {
groupBy(prop: T, opCallBack: (group: Grouping<T>, item: T) => any): Grouping<T>[];
}
// Nested property support
function getVal(obj, prop) {
const props = prop.split('.');
if (props.length === 1) {
return obj[prop];
} else {
return getVal(obj[props[0]], prop.slice(prop.indexOf('.') + 1, prop.length));
}
}
if (!Array.prototype.groupBy) {
// Return an array of 'Grouping' object
Array.prototype.groupBy = function (prop: string, opCallBack: (group: Grouping<any>, item: any) => any = null) {
return this.reduce((data, item) => {
// Get value
const val = getVal(item, prop);
// Search val
if (data.filter(g => g.key === val).length === 0) {
data.push({
key: val,
values: []
});
}
if(opCallBack) {
opCallBack(data.find(g => g.key === val), item);
}
data.find(g => g.key === val).values.push(item);
return data;
}, []);
}
}
/* End */
var a = [{a: 'aa', b: 45}, {a: 'aa', b: 45}, {a: 'aa', b: 2}, {a: 'cc', b: 4}, {a: 'cc', b: 45.6}, {a: 'bb', b: 1}];
console.log(a.groupBy('a', (group, item) => {
group.computed = group.computed || 0; group.computed += item.b
}));
// Log:
[
{
"key": "aa",
"values": [
{
"a": "aa",
"b": 45
},
{
"a": "aa",
"b": 45
},
{
"a": "aa",
"b": 2
}
],
"computed": 92
},
{
"key": "cc",
"values": [
{
"a": "cc",
"b": 4
},
{
"a": "cc",
"b": 45.6
}
],
"computed": 49.6
},
{
"key": "bb",
"values": [
{
"a": "bb",
"b": 1
}
],
"computed": 1
}
]
我希望它能有用