เมธอด filter, map, reduce ของอาเรย์
เมธอด filter map และ reduce นั้นเป็นเมธอดของอาเรย์ คุณสามารถเขียนมันด้วยตัวเองด้วยคำสั่ง for loop แต่การรู้จักกับเมธอดเหล่านี้จะทำให้การทำงานกับอาเรย์ง่ายขึ้นและรวดเร็วขึ้น เนื่องจากมันถูกออกแบบมาเพื่อแก้ปัญหาพื้นฐานที่เรามักต้องการทำกับอาเรย์ นี่เป็นเนื้อหาในบทนี้
- เมธอด filter
- เมธอด map
- เมธอด reduce
เมธอด filter
เมธอด filter ใช้สำหรับเลือกสมาชิกในอาเรย์จากเงื่อนไขที่กำหนด เมธอดรับพารามิเตอร์เป็นฟังก์ชัน Callback วนรอบสมาชิกแต่ละตัวในอาเรย์ และส่งแต่ละค่าดังในอาเรย์เข้ามายังฟังก์ชัน เราต้องสร้างเงื่อนไขโดยส่งค่ากลับเป็น true
เพื่อเลือกเอาค่าในอาเรย์ และ false
ในกรณีที่ไม่ต้องการ เมธอด filter
ส่งค่ากลับเป็นอาเรย์ใหม่ของสมาชิกที่ทำให้เงื่อนไขเป็นจริง
สำหรับตัวอย่างแรกในการใช้งานเมธอด filter
มาเขียนโปรแกรมเพื่อเลือกเอาเฉพาะตัวเลขจำนวนคู่ในอาเรย์ นี่เป็นตัวอย่าง
let numbers = [3, 4, 7, 5, 12, 6, 10, 8, 15];
let evenNumbers = numbers.filter(function (value) {
return value % 2 == 0;
});
console.log("Filtered:", evenNumbers);
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Filtered: [ 4, 12, 6, 10, 8 ]
ในตัวอย่าง เรามีอาเรย์ของตัวเลข numbers
จากนั้นเราต้องการเลือกเอาเพียงตัวเลขจำนวนคู่ในอาเรย์โดยการใช้เมธอด filter
เมธอดจะวนแต่ละค่าในอาเรย์และส่งค่าเข้ามายังฟังก์ชัน Callback ผ่านพารามิเตอร์ value
เราได้กำหนดเงื่อนไขเพื่อเลือกเอาตัวเลขโดยการส่งค่ากลับด้วยคำสั่ง return
return value % 2 == 0;
นั่นหมายความว่าทุกค่าที่ทำให้เงื่อนไขเป็นจริง จะได้รับการเลือกจากเมธอด filter
และเมธอดส่งค่ากลับเป็นอาเรย์ใหม่ของค่าที่ทำให้เงื่อนไขเป็นจริงหรือผ่านการคัดเลือก
ต่อมาเป็นการเลือกเอาออบเจ็คของพนักงานในอาเรย์ โดยเลือกเอาเฉพาะพนักงานที่มีเงินเดือนมากกว่า 50000
บาทขึ้นไปจาก Property salary
โดยการใช้เมธอด filter
นี่เป็นตัวอย่าง
let employees = [
{ name: "Andrew", salary: 62000 },
{ name: "Chris", salary: 53400 },
{ name: "Metin", salary: 32000 },
{ name: "John", salary: 58000 },
{ name: "Julia", salary: 46000 }
];
let hightSalary = employees.filter(function (value) {
return value.salary >= 50000;
});
console.log("Employees with salary greater than 50000:");
hightSalary.forEach(function (value) {
console.log(value.name);
});
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Employees with salary greater than 50000:
Andrew
Chris
John
ในตัวอย่างนี้ เรามีอาเรย์ employees
ที่เก็บออบเจ็คของพนักงานที่ประกอบไปด้วยชื่อ name
และเงินเดือน salary
และเช่นเดิม เพื่อเลือกเอาพนักงานที่มีเงินเดือนมากกว่า 50000
เราต้องสร้างเงื่อนไขที่ส่งค่ากลับเป็นจริงในกรณีที่เงินเดืิอนมากกว่า 50000
hightSalary.forEach(function (value) {
console.log(value.name);
});
เราจะได้ออบเจ็คที่ตรงตามเงื่อนไขที่ต้องการในอาเรย์ hightSalary
จากนั้นใช้เมธอด forEach
ในการวนรอบอาเรย์เพื่อแสดงชื่อของพนักงานเหล่านั้นออกมาทางหน้าจอ
นอกจากนี้เมธอด filter
ยังส่ง Index ของอาเรย์ผ่านพารามิเตอร์ที่สองเข้าไปยังฟังก์ชัน Callback อีกด้วย ในตัวอย่างนี้เป็นการเลือกเอาตัวเลขในอาเรย์เฉพาะสมาชิกที่มี Index น้อยกว่า 5
let numbers = [10, 20, 30, 40, 50, 60, 70, 80];
let minorIndexed = numbers.filter(function (value, index) {
return index < 5;
});
console.log(minorIndexed);
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
[ 10, 20, 30, 40, 50 ]
นอกจากจะใช้ค่าของอาเรย์เป็นเงื่อนไขแล้ว เราสามารถใช้ Index เป็นเงื่อนไขได้ โดยรับจากพารามิเตอร์ที่สองของฟังก์ชัน Callback ในกรณีนี้ ตัวเลขที่มี Index น้อยกว่า 5
เท่านั้นที่จะถูกเลือกจากเมธอด filter
เมธอด map
เมธอด map
ใช้สำหรับแปลงค่าในอาเรย์ให้เป็นค่าใหม่ที่เกิดจากการส่งค่ากลับของฟังก์ชัน Callback ที่ส่งเข้าไปยังเมธอด โดยการวนแต่ละค่าในอาเรย์เหมือนกับเมธอด filter
และค่าที่ส่งกลับจากฟังก์ชัน Callback จะกลายมาเป็นค่าใหม่ของอาเรย์แทน
นี่เป็นตัวอย่างของการแปลงตัวเลขในอาเรย์ให้เพิ่มขึ้นเป็นสองเท่าโดยการใช้เมธอด map
let numbers = [1, 2, 3, 4, 5, 6, 7, 8];
let doubledNumbers = numbers.map(function (value, index) {
return value * 2;
});
console.log("Doubled:", doubledNumbers);
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Doubled: [
2, 4, 6, 8,
10, 12, 14, 16
]
ในตัวอย่าง เราได้ส่งค่ากลับจากฟังก์ชัน Callback โดยการคูณค่าในอาเรย์ด้วย 2 จากคำสั่ง value * 2
เพื่อทำให้มันเพิ่มขึ้นเป็นสองเท่า และตอนนี้เราได้อาเรย์ใหม่ doubledNumbers
ที่มีตัวเลขเพิ่มขึ้นเป็นสองเท่าจากอาเรย์เดิมแล้ว
เมธอด map
นั้นส่ง Index ของอาเรย์เป็นพารามิเตอร์ที่สองของฟังก์ชันเช่นเดียวกันกับเมธอด filter
และในกรณีที่เราไม่ต้องการใช้งานมันสามารถละเว้นออกไปได้
ในตัวอย่างต่อมาจะเป็นการแปลงอาเรย์ของ String ให้เป็นออบเจ็คที่ประกอบไปด้วยรหัส ชื่อ และความยาวของชื่อ โดยการใช้เมธอด map
นี่เป็นตัวอย่าง
let names = ["Andrew", "Chris", "Metin", "John", "Brendan"];
let objects = names.map(function (value, index) {
return {
id: index + 1,
name: value
}
});
console.log(objects);
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
[
{ id: 1, name: 'Andrew' },
{ id: 2, name: 'Chris' },
{ id: 3, name: 'Metin' },
{ id: 4, name: 'John' },
{ id: 5, name: 'Brendan' }
]
เราสามารถใช้เมธอด map
เพื่อแปลงค่าในอาเรย์เป็นค่าใดๆ ได้ ในตัวอย่างนี้เราได้แปลงอาเรย์เป็นออบเจ็ค โดยใช้ Index เป็นรหัส และชื่อในอาเรย์ จะเห็นว่าเราสามารถแปลงค่าเป็นแบบไหนก็ได้ เพียงส่งกลับเป็นค่าใหม่ที่ต้องการจากฟังก์ชัน Callback
เมธอด reduce
เมธอด reduce
เป็นเมธอดที่เรียกใช้งานฟังก์ชัน Reducer ที่ส่งเป็นฟังก์ชัน Callback เข้าไปยังเมธอด และส่งค่ากลับเป็นผลจากการทำงานของฟังก์ชัน Reducer กับค่าทั้งหมดในอาเรย์แบบต่อเนื่องกัน และได้ผลลัพธ์เป็นค่าสุดท้ายเพียงค่าเดียว
สำหรับตัวอย่างพื้นฐานที่จะช่วยให้เข้าใจการทำงานของเมธอด reduce
ได้ดีที่สุดคือใช้มันสำหรับหาผลรวมของตัวเลขในอาเรย์ นี่เป็นตัวอย่าง
let numbers = [0, 1, 2, 3, 4];
let sum = numbers.reduce(function (accumulator, currentValue) {
return accumulator + currentValue;
}, 0);
console.log("Sum:", sum);
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Sum: 10
ในตัวอย่าง เป็นการใช้งานเมธอด reduce
เพื่อหาผลรวมของตัวเลขในอาเรย์ เมธอดรับฟังก์ชัน Callback เป็นพารามิเตอร์แรก และพารามิเตอร์ที่สองเป็นค่าเริ่มต้นสำหรับเมธอดเพื่อทำงาน ในตัวอย่างเราได้กำหนดเป็น 0
เพื่อเป็นค่าเริ่มต้นสำหรับหาผลรวมของตัวเลขในอาเรย์
ในการทำงานเมธอดจะวนทุกค่าในอาเรย์และส่งค่าเข้าไปยังฟังก์ชัน Callback ผ่านพารามิเตอร์ currentValue
function (accumulator, currentValue) {
return accumulator + currentValue;
}
ในรอบแรกของการทำงาน accumulator
จะมีค่าเป็น 0
ซึ่งเป็นค่าเริ่มที่กำหนดให้กับเมธอด และค่าที่ส่งกลับในฟังก์ชันจะกลายมาเป็น accumulator
ในรอบถัดไป และโปรแกรมวนทำจนถึงสมาชิกตัวสุดท้ายในอาเรย์ และค่าส่งกลับในรอบสุดท้ายจะเป็นผลลัพธ์ของเมธอด
สำหรับการทำงานของเมธอด reduce
เพื่อหาผลรวมของตัวเลขในอาเรย์จากตัวอย่างด้านบน สามารถแสดงให้เห็นในแต่ละขึ้นตอนได้ดังตารางต่อไปนี้
รอบที่ | accumulator | currentValue | ค่าส่งกลับ |
---|---|---|---|
1 | 0 | 0 | 0 + 0 |
2 | 0 | 1 | 0 + 1 |
3 | 1 | 2 | 1 + 2 |
4 | 3 | 3 | 3 + 3 |
5 | 6 | 4 | 6 + 4 => 10 |
จากในตารางนั้นจะเห็นว่าเมธอด reduce
ทำงานทั้งหมด 5 ในรอบแรก accumulator
มีค่าเริ่มต้นเท่ากับ 0
และนำไปบวกกับค่าในรอบปัจจุบัน ค่าที่ถูกส่งกลับจะกลายเป็น accumulator
ในรอบถัดไปเรื่อยๆ จนถึงการส่งกลับในรอบสุดท้ายซึ่งก็คือผลลัพธ์การทำงานของเมธอด
ในตัวอย่างถัดมาลองมาเปลี่ยนค่าเริ่มต้นในอาร์กิวเมนต์ที่สองของเมธอดเป็น 10
และนั่นจะทำให้มันถูกใช้เป็น accumulator
ในรอบแรก นี่เป็นตัวอย่าง
let numbers = [0, 1, 2, 3, 4];
let sum = numbers.reduce(function (accumulator, currentValue) {
return accumulator + currentValue;
}, 10);
console.log("Sum:", sum);
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Sum: 20
ในตัวอย่างนั้นคุณคงจะสามารถเดาได้ว่าทำไม เนื่องจากว่าเริ่มต้นเรากำหนดค่าเริ่มให้กับฟังก์ชัน Reducer เป็น 10
นั่นทำให้ค่า accumulator
ในรอบแรกเริ่มจาก 10 นั้นเอง ซึ่งสามารถแสดงการทำงานได้ดังตารางต่อไปนี้
รอบที่ | accumulator | currentValue | ค่าส่งกลับ |
---|---|---|---|
1 | 10 | 0 | 10 + 0 |
2 | 10 | 1 | 10 + 1 |
3 | 11 | 2 | 11 + 2 |
4 | 13 | 3 | 13 + 3 |
5 | 16 | 4 | 16 + 4 => 20 |
นอกจากนี้ ในการใช้งานเมธอด reduce
นั้นยังสามารถละเว้นค่าเริ่มต้นในพารามิเตอร์ที่สองได้ ถ้าหากเราทำ ค่าแรกในอาเรย์จะถูกนำมาใช้เป็นค่าเริ่มต้นแทน และอาเรย์จะเริ่มทำงานตั้งแต่สมาชิกตัวที่สองเป็นต้นไป นี่เป็นตัวอย่าง
let numbers = [0, 1, 2, 3, 4];
let sum = numbers.reduce(function (accumulator, currentValue) {
return accumulator + currentValue;
});
console.log("Sum:", sum); // Sum: 10
ในตัวอย่างนี้ เป็นโปรแกรมสำหรับหาผลรวมของตัวเลขในอาเรย์เช่นเดิม จะเห็นว่าผลลัพธ์การทำงานยังคงเป็นเท่าเดิม โปรแกรมเริ่มวนจากสมาชิกตัวที่สอง (1
) ในอาเรย์ และใช้สมาชิก (0
) เป็นค่าเริ่มต้นสำหรับ accumulator
ในรอบแรกแทน
เมธอด reduce
นั้นสามารถนำมาประยุกต์ใช้เพื่อแก้ปัญหาต่างๆ ได้หลายอย่าง ข้อดีของมันคือเราสามารถกำหนดฟังก์ชัน Reducer ซึ่งเป็นฟังก์ชัน Callback ที่สามารถทำงานเสร็จได้ในตัวของมันเอง และยังกระทัดรัดและสั้นในการเขียน ในตัวอย่างนี้เป็นการใช้เมธอด reduce
เพื่อหาค่ามากสุดและน้อยสุดในอาเรย์ของตัวเลข
let numbers = [10, 5, 2, 17, 16, 6, 18, 3];
let max = numbers.reduce(function (accumulator, currentValue) {
return accumulator > currentValue ? accumulator : currentValue;
});
let min = numbers.reduce(function (accumulator, currentValue) {
return accumulator < currentValue ? accumulator : currentValue;
});
console.log("Max:", max);
console.log("Min:", min);
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Max: 18
Min: 2
ในกรณีนี้ไม่จำเป็นต้องกำหนดค่าเริ่มต้นให้กับเมธอด reduce
เนื่องจากว่าเราต้องการนำแต่ละค่าในอาเรย์มาเปรียบเทียบกันเอง และส่งค่ากลับเป็นค่าที่มากกว่าหรือน้อยกว่าเสมอ ดังนั้นโปรแกรมเริ่มทำงานจากสมาชิกตัวที่สองของอาเรย์ซึ่งคือ 5
และใช้สมาชิกตัวแรก 10
เป็นค่าเริ่มต้นของ accumulator
return accumulator > currentValue ? accumulator : currentValue;
...
return accumulator < currentValue ? accumulator : currentValue;
ในแต่ละรอบของการทำงานเมธอดจะส่งกลับเป็นค่าที่น้อยกว่าหรือมากกว่าเสมอ นั่นทำให้ในตอนสุดท้ายผลลัพธ์ของโปรแกรมจะได้ค่าที่น้อยกว่าและมากกว่าที่เราต้องการหาจากอาเรย์ด้วยเมธอด reduce
ตัวอย่างสุดท้ายในการใช้เมธอด reduce
จะเป็นการเขีียนโปรแกรมสำหรับนับชื่อของสีในอาเรย์ว่ามีอย่างละเท่าไหร่ เราจะใช้ออบเจ็คสำหรับการนับโดยใช้ชื่อของสีเป็น Key ของออบเจ็ค ดังนั้นค่าเริ่มต้นของเมธอดจะเป็นออบเจ็ค
let colors = [
"red", "green", "yellow", "green", "blue", "red", "green"
];
let count = colors.reduce(function(object, currentValue, index) {
if (typeof object[currentValue] === 'undefined') {
object[currentValue] = 1;
} else {
object[currentValue]++;
}
return object;
}, {});
console.log('counted:', count);
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
counted: { red: 2, green: 3, yellow: 1, blue: 1 }
ในตัวอย่างนี้ เป็นโปรแกรมสำหรับนับสีในอาเรย์ว่าในแต่ละสีนั้นมีจำนวนเท่าไร และเนื่องจากเราใช้ออบเจ็คสำหรับเก็บการนับ ดังนั้นค่าเริ่มของเมธอดในอาร์กิวเมนต์ที่สองจึงเป็นออบเจ็คที่ว่างเปล่า {}
จากนั้น Property ของออบเจ็คจะถูกสร้างขึ้นมาแบบไดนามิกส์ตามค่าที่มีอยู่ในอาเรย์
if (typeof object[currentValue] === 'undefined') {
object[currentValue] = 1;
} else {
object[currentValue]++;
}
ในฟังก์ชัน Reducer เราได้ทำการตรวจสอบโดยการใช้ค่าของอาเรย์เป็น Key ว่ามันเคยถูกนับแล้วหรือไม่ โดยตรวจสอบว่ามี Property นี้อยู่แล้วหรือยัง ถ้าหากไม่เริ่มนับมันจาก 1
หรือในกรณีทีมีแล้วเพิ่มค่าขึ้นไปอีก 1
return object;
เนื่องจากออบเจ็คนั้นเก็บค่าในรูปแบบ Reference ดังนั้นค่าที่ส่งกลับจะเป็นออบเจ็คเดิมเสมอ และในตอนท้ายเราจะได้ค่าที่นับได้ทั้งหมดเป็นออบเจ็คที่มีชื่อของสีเป็น Key ในตัวแปร count
การกำหนดค่าเริ่มต้นหรือไม่นั้นอาจให้ผลลัพธ์ที่แตกต่างกันขึ้นอยู่กับว่าฟังก์ชัน Reducer ของคุณทำอะไร เช่น ในตัวอย่างการหาผลรวมเนื่องจากทั้งสองวิธี (กำหนดค่าเริ่มต้นเป็น 0 หรือไม่กำหนด) นั้นให้ผลลัพธ์เหมือนกัน แต่ในบางกรณีเช่นการหาค่ามากกว่าหรือน้อยกว่าในอาเรย์ การกำหนดค่าเริ่มต้นอาจทำให้ผลลัพธ์การทำงานไม่ถูกต้องได้
ในตอนนี้คุณคงจะเข้าใจแล้วว่าจะนำเมธอดเหล่านี้มาช่วยอำนวยความสะดวกในการเขียนโปรแกรมอย่างไร มาสรุปกันอีกครั้งว่าแต่ละเมธอดนั้นใช้ทำอะไร
- เมธอด
filter
ใช้สำหรับเลือกค่าในอาเรย์จากเงื่อนไขที่กำหนด - เมธอด
map
ใช้สำหรับแปลงค่าในอาเรย์เดิมเป็นค่าใหม่ - เมธอด
reduce
ใช้เพื่อวนรอบอาเรย์เพื่อคำนวณค่าแบบต่อเนื่องและส่งค่ากลับเป็นค่าสุดท้าย
ในบทนี้ คุณได้เรียนรู้เกี่ยวกับการใช้งานเมธอด filter map และ reduce ของอาเรย์ในภาษา JavaScript ที่สามารถอำนวยความสะดวกเมื่อต้องทำงานกับอาเรย์