ทำตัวเหล่ท่อไปกับ Higher order functions in Swift
หวัดดีชาวโลก นี่เราเดินทางเข้าสู่อีกครึ่งปีของปี 2021 แล้วหรอเนี่ย เร็วมากกกกก เอาล่ะมาเข้าเรื่องกันเถอะเนอะ สำหรับ blog นี้ก็จะตามหัวข้อเลยนะ เราจะมาพูดถึง Higher order functions in Swift
ซึ่งเนื้อหาจะมีอะไรยังไงบ้าง ไปดูกันโลดดดดดด
สิ่งที่จะพูดถึงในวันนี้
- อะไรคือ
Higher order functions
- ประโยชน์ของ
Higher order functions
Higher order functions
ที่เรานิยมนำมาใช้กันมากที่สุด
มาเริ่มกันที่หัวข้อแรกกันเลยดีกว่า
อะไรคือ Higher order functions
สำหรับชาว iOS ที่เขียนภาษา Swift จะมีคำอธิบายแค่ 2 ข้อเท่านั้น สั้นๆ กระชับ และเข้าใจง่ายแน่นอน
1. function ที่รับ argument มาเป็น function หรือ closures
2. function ที่มีการ return มาเป็น function หรือ closures
เนี่ยยยยยมีแค่นี้เลย เพียง 2 ข้อสั้นๆ กระชับเข้าใจได้ง่าย 😁😁😁
มาดูตัวอย่างที่เขียนกัน
จะเห็นว่า function combineUserData จะเป็น Higher order functions
เพราะมีการรับ function เข้ามาเป็น argument ซึ่ง function ที่จะถูกส่งเข้ามาจะเป็นการรับ string 2 ตัวเข้ามาและทำอะไรซักอย่าง แล้ว return ออกมาเป็น string และจากโค้ดจะได้ผลลัพธ์ตามรูปด้านล่างนี้
ประโยชน์ของ Higher order functions
- โค้ดจะอ่านง่ายได้จาก function เลย และโค้ดจะ clean และ clear มาก
- ง่ายต่อการ reuse กับ function อื่นๆ
- และข้อสุดท้ายสำคัญมากๆ ใช้แล้วจะรู้สึกเหล่ท่อมากๆ 😂😂😂
Higher order functions
ที่เรานิยมนำมาใช้กันมากที่สุด
- map
- compactMap
- flatMap
- reduce
- sorted
- filter
มาเริ่มดูกันที่ตัวแรกก่อนเล้ยยยยยย
- map จะเป็นการเปลี่ยน element แต่ละตัวของ array เดิม ใน closure แล้วส่งค่าของ array ใหม่กลับมา
ตัวอย่างการใช้ map
let countries: [String] = ["thailand", "india", "england", "france", "usa"]
จากตัวอย่างข้อมูลด้านบน ถ้าหากเราต้องการให้ตัวหนังสือเป็นตัวใหญ่ทั้งหมด แบบไม่ใช้ Higher order functions
ก็คงจะเขียน for loop ในลักษณะนี้กันเนอะ
var uppercasedWordsForLoop: [String] = [String]()
for country in countries {
uppercasedWordsForLoop.append(country.uppercased())
}
แต่ถ้าหากว่าเราจะใช้ Higher order functions
ล่ะจะเป็นยังไง
let uppercasedWords = countries.map { $0.uppercased() }
ผลลัพธ์
จะเห็นได้ว่าตอนเราใช้ for loop โค้ดจะค่อนข้างยาว แถมยังต้องสร้าง array อีกตัวมา append element ทีละตัวด้วย และการใช้ map โค้ดจะสั้นกระชับ และ clear ด้วย
- compactMap จะเป็น function ที่คล้ายกันกับ map เลย เพียงแต่ compactMap จะ returns array ที่จะไม่มีค่า null
ตัวอย่างการใช้ compactMap
let countries: [String?] = ["thailand", nil, nil, "india", "england", nil, "france", "usa"]
let map = countries.map { $0?.uppercased() }
let compactMap = countries.compactMap { $0?.uppercased() }
ผลลัพธ์
จากผลลัพธ์จะเห็นว่าถ้าหากเราใช้ map ตัว array ของเราจะยังคงมี element ที่เป็น null อยู่ด้วย แต่หากใช้ compact map เราจะได้ array ที่ไม่มีค่า null นั่นเอง
- flatMap จะช่วยเราจัดการกับพวก nested array หากเราใช้ flatMap กับ nested array ใดๆ จะทำให้ array นั้นกลายเป็น array 1 มิติ และเรายังใช้ flatMap เหมือน compactMap ด้วย คือค่าใน array จะไม่มี null นั่นเอง
ตัวอย่างการใช้ flatMap
let countries: [[String]] = [["thailand", "india"], ["england", "france", "usa"]]
let flatMap = countries.flatMap { $0 }
ผลลัพธ์
- reduce เป็น function ที่ให้เรา combine ทุก elements ใน array แล้ว return ข้อมูลบางอย่างออกมาด้วย type อะไรก็ได้ (Generic)
ตัวอย่างการใช้ reduce (แบบเต็ม)
let numbers: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let sum = numbers.reduce(0, { x, y in
return x + y
})
ตัวอย่างการใช้ reduce (แบบสั้น)
let sum2 = numbers.reduce(0, { $0 + $1 })
ตัวอย่างการใช้ reduce (แบบสั้นยิ่งกว่าาาาา)
let sum3 = numbers.reduce(0, +)
ผลลัพธ์
- sorted เป็น function ที่ทำงานตามชื่อเลย ก็คือการเรียงข้อมูลใร array นั่นเอง
ตัวอย่างการใช้ sorted
let toSort = [5, 3, 8, 2, 10]let sorted = toSort.sorted()
ผลลัพธ์
จากผลลัพธ์ ถ้าหากเราเรียกใช้ sorted แบบด้านบนตัวเลขจะถูกเรียงจากน้อยไปหามาก แต่ถ้าหากเราต้องการให้เรียงจากมากไปน้อยล่ะ จะเขียนยังไง ไปดูกัน
ตัวอย่างการใช้ sorted เรียงจากมากไปน้อย
let sortedShortHand = toSort.sorted { (num1, num2) -> Bool in
return num1 > num2
}
ตัวอย่างการใช้ sorted เรียงจากมากไปน้อย (แบบสั้น)
let sortedShorterHand = toSort.sorted { $0 > $1 }
ตัวอย่างการใช้ sorted เรียงจากมากไปน้อย (แบบสั้นยิ่งกว่าาาาา)
let sortedShortestHand = toSort.sorted(by: >)
ผลลัพธ์
- filter จะเป็นการ filter element ของ array เดิมด้วยเงื่อนไขที่กำหนด และใน closure จะส่งค่าของ array ใหม่กลับมา เช่น การหาเลขคู่/คี่ ใน array ของตัวเลข เป็นต้น
ตัวอย่างการใช้ filter
let numbers: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let filter = numbers.filter { $0 % 2 == 0 }
ผลลัพธ์
จะเห็นได้ว่าจากตัวอย่างทั้งหมด แต่ละ function จะทำให้เราเขียนโค้ดได้สั้นกระชับมากขึ้น และตัว function ก็ค่อนข้าง clear เมื่อได้อ่าน ซึ่งมันจะเป็นผลดีต่อเราและทีมของเราแน่นอน และที่สำคัญเขียนออกมาแล้วยังเหล่ท่อไปอี้กกกกก
สำหรับ blog นี้เนื้อหาก็จะมีเพียงเท่านี้ หวังว่าจะเป็น blog ที่มีประโยชน์กับทุกคนที่ได้เข้ามาอ่าน แล้วเจอกันใหม่ใน blog ฮ้าฟฟฟฟ