reduce และ aggregate
วิธีอื่นในการรวมสมาชิก
reduce และ aggregate เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน
จาก Fold สู่ Reduce
บางครั้งคุณต้องการรวมสมาชิกโดยไม่ต้องระบุค่าเริ่มต้นแยกต่างหาก
reduce จะใช้สมาชิกตัวแรกเป็นตัวสะสมเริ่มต้น แล้วรวมสมาชิกที่เหลือเข้าไป
reduce เป็นญาติที่กระชับกว่าของ fold เหมาะกับกรณีที่ชนิดของสมาชิกและชนิดของผลลัพธ์เหมือนกัน
พื้นฐานของ reduce
reduce รับฟังก์ชันไบนารี (a, b) แล้วพับฟังก์ชันนั้นผ่านคอลเลกชันโดยไม่มีค่าเริ่มต้นที่ระบุอย่างชัดเจน
สำหรับการหาผลรวม ฟังก์ชันนี้เพียงนำสมาชิกทุกตัวมาบวกกัน
val xs = List(1, 2, 3, 4)
val total = xs.reduce((a, b) => a + b)
@main def run(): Unit =
println(total) // 10กับดักของคอลเลกชันว่าง
เนื่องจาก reduce ไม่มีค่าเริ่มต้น การเรียกใช้กับคอลเลกชันว่างจะทำให้เกิด UnsupportedOperationException
fold และ foldLeft ปลอดภัยกับคอลเลกชันว่าง เพราะจะใช้ค่าเริ่มต้นที่ระบุไว้เป็นทางเลือก
เลือกใช้ reduce เฉพาะเมื่อคุณทราบว่าคอลเลกชันไม่ว่าง
// List.empty[Int].reduce(_ + _)
// throws UnsupportedOperationException
List.empty[Int].foldLeft(0)(_ + _) // safe, returns 0reduceOption เพื่อความปลอดภัย
reduceOption จะคืนค่าเป็น Option โดยให้ค่า None เมื่อคอลเลกชันว่าง แทนการทำให้เกิดข้อผิดพลาด
นี่เป็นวิธีที่ปลอดภัยในการลดค่าเมื่อมีความเป็นไปได้ที่คอลเลกชันจะว่าง
val xs = List(5, 9, 2)
val maybeMax = xs.reduceOption(_ max _)
@main def run(): Unit =
println(maybeMax) // Some(9)reduceLeft และ reduceRight
เช่นเดียวกับ fold, reduce มีรูปแบบที่กำหนดทิศทางด้วย
reduceLeft รวมค่าจากซ้ายไปขวา ส่วน reduceRight รวมค่าจากขวาไปซ้าย reduce แบบธรรมดาไม่รับประกันลำดับสำหรับคอลเลกชันแบบขนาน ดังนั้นให้ใช้รูปแบบที่ระบุทิศทางอย่างชัดเจนเมื่อลำดับมีความสำคัญ
val xs = List(1, 2, 3)
val l = xs.reduceLeft(_ - _) // (1-2)-3 = -4
val r = xs.reduceRight(_ - _) // 1-(2-3) = 2
@main def run(): Unit =
println((l, r)) // (-4, 2)เหตุผลที่มี aggregate
fold และ reduce ต้องการให้ชนิดของตัวสะสมและชนิดของสมาชิกมีความสัมพันธ์กันอย่างตรงไปตรงมา
aggregate คือ fold ที่ทั่วไปที่สุด โดยอนุญาตให้ตัวสะสมมีชนิดแตกต่างจากสมาชิก และบอก Scala วิธีรวมตัวสะสมบางส่วน ซึ่งสำคัญต่อการประมวลผลแบบขนาน
รูปแบบการประกาศของ aggregate
aggregate รับค่าเริ่มต้น seqop ที่พับสมาชิกหนึ่งตัวเข้าไปในตัวสะสม และ combop ที่รวมตัวสะสมสองตัวเข้าด้วยกัน
สำหรับคอลเลกชันแบบลำดับ combop แทบไม่ได้ใช้ แต่สำหรับคอลเลกชันแบบขนาน combop จะรวมผลลัพธ์จากแต่ละส่วนเข้าด้วยกัน
val xs = List(1, 2, 3, 4)
val sum = xs.aggregate(0)(
(acc, x) => acc + x, // seqop
(a, b) => a + b // combop
)
@main def run(): Unit = println(sum) // 10aggregate กับชนิดที่แตกต่างกัน
ในที่นี้ aggregate พับรายการคำให้เป็นผลรวมความยาวชนิด Int เพียงค่าเดียว
seqop จะบวกความยาวของแต่ละคำ ส่วน combop จะบวกผลรวมบางส่วนสองค่าด้วยกัน
ชนิดของตัวสะสม (Int) แตกต่างจากชนิดของสมาชิก (String)
val words = List("hi", "there", "you")
val chars = words.aggregate(0)(
(acc, w) => acc + w.length,
(a, b) => a + b
)
@main def run(): Unit = println(chars) // 10การรวมค่าแบบขนาน
พลังที่แท้จริงของ aggregate ปรากฏเมื่อใช้กับคอลเลกชันแบบขนาน
แต่ละเธรดจะพับส่วนของตนเองด้วย seqop จากนั้นจึงรวมส่วนต่าง ๆ ด้วย combop ฟังก์ชันทั้งสองช่วยให้ Scala แบ่งและรวมงานกลับได้อย่างปลอดภัย
// Conceptual: par splits the work
// val n = data.par.aggregate(0)(_ + _.length, _ + _)
// seqop runs per chunk, combop merges chunk resultsการเลือกเครื่องมือที่เหมาะสม
ใช้ reduce หรือ reduceOption เมื่อชนิดผลลัพธ์เหมือนกับชนิดสมาชิก และการรวมค่าเป็นแบบเปลี่ยนกลุ่มได้
ใช้ foldLeft เมื่อต้องการค่าเริ่มต้นหรือชนิดผลลัพธ์ที่แตกต่างกันในการประมวลผลแบบลำดับ
ใช้ aggregate เมื่อชนิดของตัวสะสมและสมาชิกแตกต่างกัน และต้องการการรวมผลที่เหมาะกับการประมวลผลแบบขนาน
// reduce: same type, non-empty, associative
// foldLeft: seed + different type, sequential
// aggregate: different type + parallel mergeการรวมค่าภายในรอบเดียว
aggregate สามารถคำนวณหลายอย่างพร้อมกันได้โดยสะสมลงในทูเพิล
ในที่นี้เราได้ทั้งผลรวมและจำนวนสมาชิกภายในรอบเดียว โดยรวมทูเพิลต่าง ๆ ใน combop
val xs = List(2, 4, 6, 8)
val (s, c) = xs.aggregate((0, 0))(
(acc, x) => (acc._1 + x, acc._2 + 1),
(a, b) => (a._1 + b._1, a._2 + b._2)
)
@main def run(): Unit = println((s, c)) // (20, 4)ตรวจสอบความเข้าใจอย่างรวดเร็ว
ตัดสินใจว่าการดำเนินการใดปลอดภัยที่สุดสำหรับรายการที่อาจว่าง
สรุปทบทวน
reduce รวมสมาชิกโดยไม่มีค่าเริ่มต้น และใช้สมาชิกตัวแรกเป็นจุดเริ่มต้น โดยจะทำให้เกิดข้อผิดพลาดเมื่อคอลเลกชันว่าง ขณะที่ reduceOption จะคืนค่า None แทน
aggregate คือ fold ที่ทั่วไปที่สุด ประกอบด้วยค่าเริ่มต้น seqop สำหรับพับสมาชิก และ combop สำหรับรวมตัวสะสมบางส่วนเพื่อทำงานแบบขนาน
เลือก reduce สำหรับการรวมค่าชนิดเดียวกันที่เปลี่ยนกลุ่มได้ เลือก foldLeft สำหรับการพับแบบลำดับที่มีค่าเริ่มต้น และเลือก aggregate เมื่อชนิดแตกต่างกันหรือต้องการทำงานแบบขนาน
คำถามที่พบบ่อย
บทเรียน “reduce และ aggregate” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “reduce และ aggregate” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Scala for Backend Engineering & Functional Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “reduce และ aggregate”
วิธีอื่นในการรวมสมาชิก คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Scala for Backend Engineering & Functional Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “reduce และ aggregate” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม
ได้ บทเรียน Scala for Backend Engineering & Functional Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- คิดแบบเรียกซ้ำ
- รูปแบบตัวสะสม
- foldLeft และ foldRight
- reduce และ aggregate