[Kotlin] map reduce filter – รวมคำสั่งดีๆ ที่ใช้กับ List

หนึ่งในความสามารถน่ารักๆ ของภาษา Kotlin คือการใช้ lambda (หรือก็คือ Closure / Anonymous Function นั่นเอง ) จัดการกับข้อมูล Collection ประเภท List

ซึ่งคำสั่งที่ตัวภาษา build-in มาให้ที่ใช้ได้นั้นมีมากมายสุดๆ บล๊อกนี้เลยจะรวบรวมคำสั่งที่ใช้กับ List พร้อมตัวอย่างเอาไว้

คำสั่งหมวด Element

forEach / forEachIndexed

เป็นการวนลูปข้อมูลทุกตัวใน list ซึ่ง iterator ของข้อมูลแต่ละตัวจะแทนด้วยคีย์เวิร์ด it (ตามมาตราฐานของภาษา Kotlin)

สำหรับ forEach จะเป็นการวน element ทุกตัว แต่ถ้าต้องการ counter หรือตัวนับ index ด้วยสามารถเปลี่ยนไปใช้ forEachIndexed แทนได้ โดยการเขียนจะต้องรับ parameter 2 ตัวคือ key กับ value มา

ในภาษา Kotlin การใช้ forEach ไม่จำกัดว่าจะต้องเขียนแบบ pure function (ฟังก์ชันที่ห้ามยุ่งกับตัวแปรหรือค่าภายนอก) ทำให้เราสามารถดึงค่านอก lambda มาใช้ด้วยได้ (แต่ก็ไม่ควรทำนะ ถึงมันจะทำได้ก็เถอะ)

elementAt / elementArOrElse / elementArOrNull

เป็นการขอข้อมูลในตัวแหน่งที่ระบุ จริงๆ มันก็เหมือนกับการ access List ด้วยการใช้ [ ] แบบธรรมดา แต่เรามักจะใช้กับกรณีที่ไม่แน่ใจว่าข้อมูลตำแหน่งนั้นมีอยู่จริงหรือเปล่า

first / firstOrNull / last / lastOrNull

ใช้ในการขอข้อมูลตัวแรกสุด (หรือตัวหลังสุด) ของ List โดยข้อแตกต่างระหว่าง first กับ firstOrNull (และ last กับ lastOrNull) คือถ้าใช้แบบไม่มี OrNull แล้วไม่มีข้อมูลตัวนั้นขึ้นมาจะเจอ NoSuchElementException ตอนรันจริง

แต่นอกจากการข้อ first กับ last แบบธรรมดา เราสามารถใส่ lambda ลงไปได้ด้วย เช่น “ขอตัวแรกที่มีค่ามากกว่า 25”

indexOf / indexOfFirst / indexOfLast

คล้ายๆ กับ indexOf ในภาษา Javaคือค้นหาตำแหน่งของข้อมูลใน list (ตอบกลับเป็น index ตำแหน่งที่หาเจอ) … ในกรณีที่หาข้อมูลตัวนั้นไม่เจอเลยจะ return ค่าเป็น -1

ส่วนข้อแตกต่างระหว่าง indexOf กับ indexOfFirst กับ indexOfLast คือ indexOf จะหาข้อมูลตัวนั้นตรงๆ เลย … แต่ indexOfFirst กับ indexOfLast จะหาด้วยเงื่อนไข lambda

single / singleOrNull

ใช้สำหรับการขอข้อมูลที่ต้องมีเพียงตัวเดียวใน list ถ้าข้อมูลที่ค้นหามีมากกว่า 1 ตัวจะ throw IllegalArgumentException ออกมา

คำสั่งหมวด Aggregate

any

ใช้สำหรับเช็กว่าข้อมูลที่อยู่ในลิสต์มีอย่างน้อย 1 ตัวที่ตรงกับเงื่อนไขของเรา เราจะต้องเขียน lambda ในรูปของ condition true/false

all

เหมือนกับคำสั่ง any แต่เป็นการเช็กว่าข้อมูลในลิสต์ทุกตัวต้องตรงกับเงื่อนไข

none

เป็นส่วนกลับของ all คือแทนที่จะเช็กว่าข้อมูลทุกตัวตรงกับเงื่อนไข อันนี้จะเป็นการเช็กว่าไม่มีข้อมูลตัวไหนตรงกับเงื่อนไขแทน

count

นับจำนวนข้อมูลที่ตรงกับเงื่อนไข

contains / containsAll

เช็กว่าใน list มีข้อมูลตัวนั้นๆ หรือเปล่า ถ้าเป็น contains จะหาแค่ 1 ตัว ส่วน containsAll จะหาแบบหลายตัวและต้องเจอทุกตัวถึงจะตรงเงื่อนไข

max / maxBy / min / minBy

เป็นการหาค่ามากที่สุด (หรือน้อยที่สุด) ใน List โดยเราสามารถใส่เงื่อนไขการหาแบบ lambda ได้ด้วย maxBy (และminBy)

หรือถ้า List ของเราเป็นตัวแปรชนิดอื่น min กับ max จะทำงานเมื่อ class นั้น implements มาจาก Comparable (แบบเดียวกับ Java เลย)

sum / sumBy

หาผลรวมค่าทั้งหมดใน List หรือใช้แบบระบุตัวที่จะให้ sum ผ่าน lambda ด้วย sumBy

หมวด Map

map / mapIndexed

เป็นการแปลงข้อมูลทุกตัวด้วยเงื่อนไขแบบเดียวกัน ถ้าต้องการ index ด้วยให้ใช้ mapIndexed

mapNotNull

ใช้ในกรณีที่ List นั้นมีสมาชิกบางตัวที่เป็น null แล้วไม่ต้องการยุ่งกับค่าพวกนั้น

flatMap

ปกติการ map จะมีจำนวนข้อมูล input เท่ากับ output เช่นลิสต์เดิมมี 10 ตัว ลิสต์ใหม่ที่ได้หลัง map ก็จะได้ 10 ตัว

แต่ถ้าเป็น flatMap จะเป็นการขยายข้อมูล output เช่นถ้าข้อมูลเข้า 10 ตัวอาจจะทำให้มีข้อมูลออก 20 ตัว (ถ้าต้องการให้ output มีจำนวนน้อยลงจะใช้ filter)

หมวด Filter และการ Sub-list

filter / filterNot

ใช้ในการกรองข้อมูลใน List ให้เหลือแค่ตัวที่ตรงตามเงื่อนไข ส่วน filterNot จะเป็นตัวที่ไม่ตรงเงื่อนไขแทน

filterNotNull

เหมือนกับ filter แต่จะเลือกเฉพาะตัวที่ไม่ใช่ null มาคิด

subList

ใช้ตัดส่วนของ List ออกมา parameter แรกคือจุดเริ่ม ส่วน parameter ที่สองคือจุดสิ้นสุด (ไม่รวมตัวนั้น)

take / takeLast / takeWhile

เป็นรูปย่อของ subList ในกรณีที่ต้องการแค่ x ตัว take จะเริ่มนับจากหัวแถว, takeLast จะเริ่มนับจากท้ายแถว, ส่วน takeWhile จะเอาไปเรื่อยๆ ถ้ายังตรงเงื่อนไขใน lambda

drop / dropLast / dropWhile

คล้ายๆ กับ take แต่อันนี้จะเป็นการลบข้อมูลออกแทน (พูดง่ายๆ คือส่วนกลับของ take)

slice

ใช้สำหรับเลือกข้อมูลออกมา จัดตามลำดับ index ที่ระบุให้ไป

หมวด Reduce

fold / foldRight

ใช้เพื่อลดข้อมูลทั้ง List ให้เหลือแค่ค่าเดียวด้วยวิธีการที่ระบุใน lambda โดย fold จะเริ่มคำนวณค่าทีละคู่จากด้านหัวแถวไปจนถึงท้ายแถว (parameter แรกคือค่าเริ่มต้น) ส่วน foldRight จะคิดเหมือนกันแค่คิดจากด้านท้ายแถวมาด้านหน้า

reduce / reduceRight

เหมือนกับ fold แต่จะไม่มีการกำหนดค่าเริ่มต้น … reduce จะใช้ค่าตัวแรกใน List เป็นค่าเริ่มต้นแทน

หมวดการจัดกลุ่ม List

partition

สำหรับใช้จัดกลุ่มข้อมูล แยกตามเงื่อนไขใน lambda (ต้องเป็นเงื่อนไข boolean เท่านั้น) … โดยจะแยกข้อมูลออกเป็นข้อมูลชนิด Pair ข้อมูลที่ตรงกับ true จะอยู่ในกลุ่มแรก นอกนั้นจะอยู่กลุ่มที่สอง

groupBy

สำหรับใช้จัดกลุ่มข้อมูล เหมือนกับ partition แต่สามารถจัดกลุ่มได้มากกว่า 2 กลุ่ม

concat

การต่อ List ใน Kotlin นั้นทำได้ง่ายๆ ด้วยเครื่องหมาย +

zip

ใช้เพื่อผสาน List 2 ตัวเข้าด้วยกันแบบ “ตัว-ต่อ-ตัว” ถ้าลิสต์ 2 ตัวมีขนาดไม่เท่ากัน จะยึดตัวสั้นกว่าเป็นเกณฑ์ … ข้อมูลในลิสต์ทั้ง 2 ตัวไม่จำเป็นต้องเป็นชนิดเดียวกันก็ได้ ผลที่ได้จะออกมาเป็น Pair เสมอ

ส่วนใหญ่ zip ไม่หากรณีใช้งานค่อยข้างยาก มักใช้กับ foreach ที่ต้องการวนลูป List 2 ตัวพร้อมๆ กันทีละ indexๆ

reverse

ใช้เพื่อกลับ List จากหัวไปท้าย

หมวดการเรียงข้อมูล

sorted / sortedDecending

ใช้เพื่อเรียงข้อมูล จากน้อยไปมาก (และใช้ sortedDecending เมื่ออยากเรียงจากมากไปน้อย) ถ้าข้อมูลเป็น object จะเรียงได้เมื่อ class นั้น implements มาจาก Comparable (แบบเดียวกับ Java เลย)

sortedBy / sortedDecendingBy

เป็นการเรียงแบบใส่เงื่อนไขว่าจะใช้ attribute อะไรเป็นหลักในการเรียง

sortWith

เรียงข้อมูลโดยกำหนดว่าให้เรียงตามฟิลด์ไหนบ้างตามลำดับ ส่วนใหญ่จะใช้กับฟังก์ชันช่วยเหลือของ Kotlin คือ compareBy จากนั้นเราจะกำหนดว่าจะให้เทียบข้อมูลด้วยฟิลด์ไหน (ถ้าค่าเท่ากับ จะใช้ฟิลด์ต่อไปเช็กแทน) ถ้าเทียบกับ Java คือการใช้คลาส Compactor ในการเปรียบเทียบค่อ

30 Total Views 0 Views Today
Ta

Ta

สิ่งมีชีวิตตัวอ้วนๆ กลมๆ เคลื่อนที่ไปไหนโดยการกลิ้ง .. ถนัดการดำรงชีวิตโดยไม่โดนแสงแดด ปัจจุบันทำงานเป็นโปรแกรมเมอร์ให้กับเว็บไซต์ยอดนิยมแห่งหนึ่ง งานอดิเรกคือ เขียนโปรแกรม อ่านหนังสือ เขียนบทความ วาดรูป และ เล่นแบดมินตัน

You may also like...

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องที่ต้องการถูกทำเครื่องหมาย *