สมมติว่าเรามีอาร์เรย์สองมิติที่เก็บข้อมูลเกี่ยวกับสีและผลไม้ดังนี้:
const data = [ ['orange', 'fruit'], ['red', 'color'], ['green', 'color'], ['orange', 'color'], ['banana', 'fruit'], ['blue', 'color'], ['lemon', 'fruit'], ['mango', 'fruit'], ['lemon', 'color'] ];
เราต้องเขียนฟังก์ชันที่รับอาร์เรย์นี้และคืนค่าอาร์เรย์ของอ็อบเจกต์ที่จัดกลุ่มผลไม้และสีตามหมวดหมู่ของมัน ในตัวอย่างนี้มีเพียงสองหมวดหมู่คือ 'fruit' และ 'color' ดังนั้นผลลัพธ์ที่คาดหวังคืออาร์เรย์ของอ็อบเจกต์สองตัว:
[
{
group: 'fruit',
value: ['orange', 'banana', 'lemon', 'mango']
},
{
group: 'color',
value: ['red', 'green', 'orange', 'blue', 'lemon']
}
]
หมายเหตุ: แม้ตัวอย่างนี้จะมีเพียงสองหมวดหมู่ แต่เราต้องเขียนโซลูชันที่ทำงานได้กับจำนวนหมวดหมู่แบบไดนามิก ไม่ได้จำกัดแค่สองหมวดหมู่เท่านั้น
วิธีแก้ปัญหา
เราจะใช้เมธอด Array.prototype.reduce() สำหรับแต่ละซับอาร์เรย์ เราจะตรวจสอบว่ามีกลุ่มที่ตรงกันอยู่แล้วหรือไม่ หากมี ให้เพิ่มค่าใหม่เข้าไปใน property value ของกลุ่มนั้น มิฉะนั้น ให้สร้างอ็อบเจกต์ใหม่สำหรับกลุ่มนั้นและเพิ่มเข้าไปในอาร์เรย์สะสม
ตัวอย่างโค้ด
const data = [
['orange', 'fruit'],
['red', 'color'],
['green', 'color'],
['orange', 'color'],
['banana', 'fruit'],
['blue', 'color'],
['lemon', 'fruit'],
['mango', 'fruit'],
['lemon', 'color']
];
const groupData = arr => {
return arr.reduce((acc, val) => {
const [value, groupName] = val;
const groupIndex = acc.findIndex(el => el?.group === groupName);
if (groupIndex !== -1) {
acc[groupIndex].value.push(value);
} else {
acc.push({
group: groupName,
value: [value]
});
}
return acc;
}, []);
};
console.log(groupData(data));
ผลลัพธ์
ผลลัพธ์ในคอนโซลจะเป็นดังนี้:
[
{ group: 'fruit', value: ['orange', 'banana', 'lemon', 'mango'] },
{ group: 'color', value: ['red', 'green', 'orange', 'blue', 'lemon'] }
]