按数组中的对象分组最有效的方法是什么?
例如,给定此对象数组:
[
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
]
我正在表格中显示这些信息。我想通过不同的方法进行分组,但我想对值求和。
我将Undercore.js用于其groupby函数,这很有用,但并不能完成全部任务,因为我不希望它们“拆分”,而是“合并”,更像SQL groupby方法。
我要找的是能够合计特定值(如果需要)。
因此,如果我按阶段分组,我希望收到:
[
{ Phase: "Phase 1", Value: 50 },
{ Phase: "Phase 2", Value: 130 }
]
如果我组了阶段/步骤,我会收到:
[
{ Phase: "Phase 1", Step: "Step 1", Value: 15 },
{ Phase: "Phase 1", Step: "Step 2", Value: 35 },
{ Phase: "Phase 2", Step: "Step 1", Value: 55 },
{ Phase: "Phase 2", Step: "Step 2", Value: 75 }
]
是否有一个有用的脚本,或者我应该坚持使用Undercore.js,然后遍历生成的对象,自己计算总数?
此解决方案采用任意函数(而不是键),因此比上述解决方案更灵活,并允许箭头函数,这与LINQ中使用的lambda表达式类似:
Array.prototype.groupBy = function (funcProp) {
return this.reduce(function (acc, val) {
(acc[funcProp(val)] = acc[funcProp(val)] || []).push(val);
return acc;
}, {});
};
注意:是否要扩展Array的原型取决于您。
大多数浏览器支持的示例:
[{a:1,b:"b"},{a:1,c:"c"},{a:2,d:"d"}].groupBy(function(c){return c.a;})
使用箭头函数(ES6)的示例:
[{a:1,b:"b"},{a:1,c:"c"},{a:2,d:"d"}].groupBy(c=>c.a)
以上两个示例都返回:
{
"1": [{"a": 1, "b": "b"}, {"a": 1, "c": "c"}],
"2": [{"a": 2, "d": "d"}]
}
var arr = [
{ Phase: "Phase 1", `enter code here`Step: "Step 1", Task: "Task 1", Value: "5" },
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
];
创建并清空对象。循环遍历arr并添加使用Phase作为obj的唯一键。在循环遍历arr时,保持更新obj中的键总数。
const obj = {};
arr.forEach((item) => {
obj[item.Phase] = obj[item.Phase] ? obj[item.Phase] +
parseInt(item.Value) : parseInt(item.Value);
});
结果如下:
{ "Phase 1": 50, "Phase 2": 130 }
循环通过obj形成表单和resultArr。
const resultArr = [];
for (item in obj) {
resultArr.push({ Phase: item, Value: obj[item] });
}
console.log(resultArr);
let x = [
{
"id": "6",
"name": "SMD L13",
"equipmentType": {
"id": "1",
"name": "SMD"
}
},
{
"id": "7",
"name": "SMD L15",
"equipmentType": {
"id": "1",
"name": "SMD"
}
},
{
"id": "2",
"name": "SMD L1",
"equipmentType": {
"id": "1",
"name": "SMD"
}
}
];
function groupBy(array, property) {
return array.reduce((accumulator, current) => {
const object_property = current[property];
delete current[property]
let classified_element = accumulator.find(x => x.id === object_property.id);
let other_elements = accumulator.filter(x => x.id !== object_property.id);
if (classified_element) {
classified_element.children.push(current)
} else {
classified_element = {
...object_property,
'children': [current]
}
}
return [classified_element, ...other_elements];
}, [])
}
console.log( groupBy(x, 'equipmentType') )
/* output
[
{
"id": "1",
"name": "SMD",
"children": [
{
"id": "6",
"name": "SMD L13"
},
{
"id": "7",
"name": "SMD L15"
},
{
"id": "2",
"name": "SMD L1"
}
]
}
]
*/