Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> JavaScript

วิธีมีประสิทธิภาพสูงสุดในการ groupBy บนอาร์เรย์ของอ็อบเจ็กต์ - JavaScript

สมมติว่าเรามีอาร์เรย์ของอ็อบเจ็กต์แบบนี้:

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" }
];

เราต้องเขียนฟังก์ชัน JavaScript ที่รับอาร์เรย์ดังกล่าวเป็นอาร์กิวเมนต์แรก เป้าหมายของเราคือให้สามารถจัดกลุ่มอาร์เรย์ที่ให้มาได้ตามคุณสมบัติหลายคุณสมบัติหรือคุณสมบัติเดียว (ที่ระบุโดยอาร์กิวเมนต์ที่สอง สาม)

ดังนั้น ถ้าเราทำ groupBy Phase เราควรได้:

const output = [
  { Phase: "Phase 1", Value: 50 },
  { Phase: "Phase 2", Value: 130 }
];

และถ้าเราทำ groupBy Phase / Step เราควรได้:

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 }
];

ตัวอย่างโค้ด

โค้ดสำหรับทำสิ่งนี้คือ:

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'));

ผลลัพธ์

ผลลัพธ์ในคอนโซลจะเป็นดังนี้:

[ { 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 }
]