Giả sử chúng ta có mảng đối tượng như sau:
const arr = [
{ 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" }
];
Cần viết hàm nhận mảng như vậy làm đối số đầu tiên. Mục đích là nhóm mảng dựa trên nhiều thuộc tính hoặc một thuộc tính đơn lẻ (chỉ định bằng đối số thứ hai, thứ ba).
Nếu groupBy Phase, kết quả:
const output = [
{ Phase: "Phase 1", Value: 50 },
{ Phase: "Phase 2", Value: 130 }
];
Nếu groupBy Phase / Step, kết quả:
const output = [
{ 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 }
];
Ví dụ
Mã thực hiện như sau:
const arr = [
{ 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" }
];
const groupBy = (array, groups, valueKey) => {
const map = new Map;
groups = [].concat(groups);
return array.reduce((acc, val) => {
groups.reduce((accu, value, ind, { length }) => {
let child;
if (accu.has(val[value])) {
return accu.get(val[value]);
};
if (ind + 1 === length) {
child = Object
.assign(...groups.map(value => ({ [value]: val[value]
})), { [valueKey]: 0 });
acc.push(child);
}
else {
child = new Map;
};
accu.set(val[value], child);
return child;
}, map)[valueKey] += +val[valueKey];
return acc;
}, []);
};
console.log(groupBy(arr, 'Phase', 'Value'));
console.log(groupBy(arr, ['Phase', 'Step'], 'Value'));
Kết quả
Kết quả trong console sẽ là:
[ { 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 }
]