You are on page 1of 6

Lambda, Map, Filter, Reduce

กอนเปนแลมบดา
การนิยามฟงกชัน เพื่อใหเรียกฟงกชันใหใชงานตามชื่อ เปนวิธีการใชงานซ้ําของสิ่งที่สรางไวแลว แตถาเราไมตองการ
ใชงานซ้ํา เพียงแคตองการใช ณ เวลานั้น ก็ไมจําเปนตองนิยามฟงกชัน ใหใชงานในระยะตอไป
เรามาเริ่มทําความเขาใจ แลมบ จาก การสรางฟงกชัน ที่ทําหนาที่บวกยกกําลังสอง ของตัวแปรเขาหนึ่งตัวแลวคืนคา
ผลการยกกําลัง ดังตัวอยางตอไปนี้

Code 1.
>>> def powerOf(x):
... return x*x
...
>>> powerOf(-2)
4

จากตัวอยางนี้ เราไดฟงกชัน ที่นําไปใชงานตอในชื่อ powerOf( ) โดยฟงกชันนี้ไมมีอะไรซับซอน เราอาจไม


จําเปนตองสรางเปนฟงกชันใหเสียเวลาก็ได แตขอดีของการสรางฟงกชัน คือ ไดชื่อที่สื่อความหมายไดดีกวา สรางเงื่อนไข
ภายในฟงกชันได และใชฟงกชันเปนตัวแปรของฟงกชันได เชน powerOf(powerOf(2))
อยางในกรณีนี้ หากเราสรางเปนฟงกชันเฉพาะกิจ ซึ่งเรียกวา ฟงกชันไมมีชื่อ (anonymous function) และชื่อ
อยางเปนทางการเรียกวา แลมบดา

มาเปนแลมปดา
การเขียนโปรแกรมเปนแลมบดา ใหความสะดวกมากกวาการสรางเปนฟงกชัน ประการแรกคือ ใชจํานวนการพิมพ
คําสั่งนอยกวา ดวยไมตองเขียนเต็มรูปแบบฟงกชัน ประการตอมา เขาใจคําสั่งไดงายกวาเพราะเนื้อความคําสั่งมีความหมายใน
ตัว
จากตัวอยางที่ผานมา ที่เขียนฟงกชันยกกําลังสอง ตอนนี้ปรับปรุงใหมใหเปนแลมบดา ซึ่งจะคืนคาผลดําเนินการเลข
ยกกําลังสอง

Code 2.
>>> doubleOf = lambda x : x*x
>>> doubleOf(-4)
16

มีสิ่งเพิ่มเติมคือ ตองเขียนคําสั่งแจงวาเปน แลมบดา ดวยคีเวิรดวา lambda ตามตัวตัวแปร ซึ่งสมมติวาชื่อ x (ใชชื่อ


ตัวแปรเปนอะไรก็ได) ผลการดําเนินการจะตามดวยเครื่องหมาย โคลอน ( : )
มาถึงตอนนี้ จะเห็นวา การใชแลมบดา ไมมีอะไรพิเศษกวา การใสคียเวิรด lambda ในภาษาอื่น เชน C#, Java,
PHP ใชเครื่องหมาย => หรือ -> แทน คําวา lambda
ในเมื่อตัวแปร doubleOf แทนแลมบดา ตัวแปรยอมสงตอแลมบดาไดดวย เขน เราตองการให ตัวแปร powerOf
เปนอีกตัวหนึ่งของ doubleOf จะเขียนสงตอตัวแปรไดวา

Code 3.
>>> powerOf = doubleOf

เอกสารประกอบการสอน การเขียนโปรแกรมดวยภาษา Python วิทยาลัยเซาธอีสบางกอก 1


>>> powerOf(4)
... 16

ความนาใชของแลมบดา ไมเพียงการใชงานสรางไดเร็ว แตประโยชนที่พิเศษกวา คือ การสรางแลมบดา เพื่อเปนตัว


แปรเขากับฟงกชันอื่น โดยเฉพาะ ฟงกชัน map, filter, และ reduce เพราะฟงกชันเหลานี้ ตองใชรูปแบบการเขียนโปรแกรม
เชิงฟงกชัน (functional programming)

การเขียนโปรแกรมเชิงฟงกชัน
เทคนิคการเขียนโปรแกรมเชิงฟงกชันคือ การสรางการทํางานบนขอมูลที่ไมอานแกไขได (immutable) จึงทําให
ฟงกชันอื่นใชขอมูลเดียวกันได โดยไมผลกระทบตอกัน ลักษณะนี้ถือวาไมใชสถานการณเปลี่ยนแปลงรวมกัน (no state
sharing) จึงไมผลกระทบออกไปยังภายนอกโปรแกรม (no side effects)
การอานขอมูลในลักษณะสงตอ ของฟงกชันอีกทีหนึ่ง หรือสงฟงกชันเปนตัวแปรของฟงกชัน เปนวิธีที่ใชนิยมใชของ
แลมบดา อยางในกรณีฟงกชันการเรียง sorted(data, key) ขอมูล data อยูในรูปขอมูล list และ key เปนเงื่อนไขการเรียง
เมื่อใหการใชเงื่อนไขการเรียงเปน แลมบดา ที่รับขอมูลตอจาก data เปนขอมูลเขาของแลมบดา แลวสงตอไปยังตัวแปร key
ของฟงกชัน sorted อีกที ดังตัวอยางการใชงาน ดังนี้

Code 4.
>>>num = [100, 200, 150]
>>>sorted(num, key:lambda n: n)
[100, 150, 200]

ยังมีกรณีการใชงานแลมบดา เปนตัวแปรของฟงกชัน ที่นาสนใจ อีกหลายตัว เชน map, filter, reduce ซึ่งเปน


ฟงกชันที่สําคัญที่ชวยการดําเนินการขอมูลไดงายดายขึ้น

map( )
ฟงกชัน map( ) ใชในการเปลี่ยนแปลงขอมูล ในกลุมขอมูล เชน list, set, tuple, และ dict และจะคืนขอมูลที่
เปลี่ยนแปลงแลวกลับไปตามชนิดกลุมขอมูลนั้น เมื่อใชใสกลับไปในชนิดขอมูลนั้น เชน ใชดําเนินการกับ list ก็จะคืนคาเปน
ชนิด list เมื่อใสกลับลงไปใน list ดังตัวอยางตอไปนี้
Code 5.
>>> nums = [2,4,5]
>>> result = map(lambda x : x**2, nums)
>>>list_sqr = list(result)
>>> print(list_sqr)
[4, 16, 25]

ซึ่งมีความหมายเหมือนกัน ตัวอยางตอไปนี้ที่กําหนดคาลง list ทันทีที่ทําการปรับปรุงขอมูลดวย map

Code 6.
>>> nums = [2,4,5]
>>> list_sqr = list(map(lambda x : x**2, mums))
>>> print(list_sqr)
[4, 16, 25]
ดังตัวอยางการใชนี้ รูปแบบ การใช map จะอยูในรูปทั่วไปคือ:
map(function, collection)

เอกสารประกอบการสอน การเขียนโปรแกรมดวยภาษา Python วิทยาลัยเซาธอีสบางกอก 2


โดยให function แทนดวยฟงกชัน หรือ แลมบดา และ collection แทนดวยกลุมขอมูล list หรือ tuple หรือ set
หรือ dict
ทีนี้ลองใช map กับ ชนิดขอมูล dict บาง สมมติใหตองการเปลี่ยนแปลงขอมูลบางรายการของ dict ใหมีขอมูลตาม
เงือ่ นไขที่กําหนดใหใหม
Code 7.
>>> cat = dict({'name':'cat','color':'black'})
>>> dic = dict(map(lambda x: (x[0], 'white' if x[1]=='black' else x[1]), cat.items()))
>>> print(dic)
{'name': 'cat', 'color': 'white'}

ใหสังเกตวาตัวอยางการใช dict นี้ มีตัววิ่งใน dict ที่กําหนดเปนตัวแปร x การจากใชตัววิ่ง items( ) และตัววิ่งมีคา


เปนคู จึงแทนแตละตัวดวย x[0] และ x[1]
หากเราไมเขียนการเปลี่ยนแปลงดวยการใช map ก็สามารถเขียนดวยวิธีทั่วไปได เชน

list_sqr = list(map(square, n))

โดยที่ square แทนดวยฟงกชันที่นิยามมากอน ที่คืนคาผลคูณยกกําลังสอง n คือ ขอมูลประเภท list ดังนั้นเมื่อ


เขียนขอมูลเต็มรูปแบบจะเขียนไดวา
Code 8.
>>> def square(i):
... return i**2
>>> list_sqr = list(map(square, [2, 4, 5]))
>>> print(list_sqr)
[4, 16, 25]

แตดูเหมือนการใชแบบงายๆ นี้ สามารถทําไดโดยไมตองใช map ก็ไดเพราะ Python รองรับการปรังปรุงขอมูลผาน


คําสั่งกอนใช for ดังเขียนใหมอีกครั้งไดวา:
Code 9.
>> list_sqr = [x**2 for x in [2,4,5]]
>>> print(list_sqr)
[4, 16, 25]

ดูเหมือนวิธีนี้จะนาใชกวา ถาจะใสเงื่อนไข ใหซับซอนขึ้น เชน ใสเงื่อนไข if ใหตัววิ่งมีคามากกวา 2 แตถาไมใช ก็ให


คืนคาปกติ (ระวังวา จะตองมีเงื่อนไข else ดวย เพราะจะตองมีการคืนคาเสมอ) ดังตัวอยางตอไปนี้
Code 10.
>>> list_sqr = [x**2 if x>2 else x for x in [2,4,5]]
>>> print(list_sqr)
[2, 16, 25]

ถาสามารถใชงานโดยไมตองใชฟงกชัน map( ) ก็จะดีเพราะตัวอยางกอนหนานี้ก็ดูเขาใจงายดี เพราะสวนหนาเปน


เหมือนการ map( ) สวนหลัง (for) เปนเหมือน list ใชแลวนี้เปนการใช map( ) อยางยอใน list นั้นเอง แตถา การใสเงื่อนไขที่

เอกสารประกอบการสอน การเขียนโปรแกรมดวยภาษา Python วิทยาลัยเซาธอีสบางกอก 3


ซับซอนมาก มีหลายคําสั่งรวมทํางาน การใช map( ) อยางยอจะเริ่มยุงยากตอการทําความเขาใจ ทางเลือกคือ กลับไปใช
แลมปหรือ หรือฟงกชัน ใสลงไปใน map( )
ที่ผานมายกตัวอยางกับ list อยางที่กลาวตั้งแตตนวา map( ) ใชไดกับทุกกลุมชนิดขอมูล ตัวอยางตอไปนี้ใชกับ dict
ที่ใชในการแปลงคาของ dict ใหมีคาคีย เปนอักษรตัวแรกเปนตัวใหญ

Code 11.
dict_1 = [{'title':'python', 'price':200}, {'title': 'ruby', 'price':300}]

list1 = list(map(lambda x : x['title'], dict_1)) # Output :['python', 'ruby']

list2 = list(map(lambda x : x['price']*10, dict_1)) # Output : [1000, 3000]

list3 = list(map(lambda x : x['title'].capitallize(), x['price']))


#Output : [{'Title':'python', 'price':200}, {'title': 'Ruby', 'price':300}]

การดําเนินการกับหลาย ตัวแปรเขา กับหลายตัวแปรกลุมขอมูล ก็อีกวิธีหนึ่ง ที่ใชกับ map( ) ได เชน การบวกเลข


ของสองกลุมขอมูล
Code 12.
>>> list1 = [2,4,6]
>>> list2 = [3,5,7]
>>> list3 = list(map(lambda x,y : x+y, list1, list2))
>>> print(list3)
[5, 9, 13]

ในไพธอน มีลักษณะคลายกับ การใช ฟงกชัน zip( ) หากยังจํากันได ในบทที่วาดวย กลุมขอมูล list, set, map อาจ
ทดลองเขียนใหมในรูปแบบ zip( ) หรือ แบบ map( ) อยางยอทดสอบความเขาใจ

filter( )
การเพิ่มเงื่อนไข เพื่อคัดกรองขอมูล เราไดเคยทํามาแลว ในการใชเงื่อนไข if ใน list หรือใน map( ) แตถาตองใชใน
เต็มรูปแบบซึ่งมีคําสั่งนี้โดยตรง คือ filter( ) รูปแบบการใชงานคือ

filter(function, iterable)

โดยที่ function คือฟงกชันทั่วไปหรือแลมบดา ที่ตองการดําเนินการไดกับ iterable โดย iterable คือ กลุมขอมูลที่


วนอานได เชน list, set, tuple, และ dict
สมมุตวาตองการคัดกรองขอมูล ในรายการ list ที่มีมากกวา 2 ซึ่งทําเพียงคัดกรอง แลวเก็บลง list ในแบบนี้เปนวิธี
งาย ที่เคยพบมาแลว
Code 13.
>>> list_filter = list(filter(lambda x: x>2, [2,4,6]))
>>> print(list_filter)
[4, 6]

จากตัวอยางนี้ จะเห็นไดวา เพียงใส คียเวิรด filter โดยมี แลมบดา เปนฟงกชันเงื่อนไข ที่ใชดําเนินการกับกลุม


ขอมูล list

เอกสารประกอบการสอน การเขียนโปรแกรมดวยภาษา Python วิทยาลัยเซาธอีสบางกอก 4


ในเมื่อ map( ) มีการเชียนอยางยอได filter( ) ก็นาจะมีการเขียนอยางยอได เดาไดเลยวานาจะมีเชนกัน ลองดู
ตัวอยางตอไปนี้ ใชงาน filter( ) อยางยอใชงานไดผลเหมือนเดิมทุกประการ
Code 14.
>>> list2 = [x for x in [2,4,6] if x>2]
>>> print(list2)
[4, 6]

reduce( )
ฟงกชันนี้ทํางานแปลกวาที่ฟงกชันที่ผานมา อยางแรกคือ ฟงกชันนี้ ตองผานการนําเขาจาก functools กอน ซึ่งใช
งานกับ Python 3 แตสําหรับ Python 2 ไมจําเปนตองนําเขา อยางที่สองคือ ฟงกชัน reduce( ) นี้ จะคืนคาเดียว ไมคืนเปน
กลุมขอมูล เชน การหารวมกันภายใน list ซึ่งจะคืนคาทั้งหมดใน list ที่บวกกัน และคานี้เปนคาเดียว ดังยกตัวอยางไดดังนี้
Code 15.
>>> from functools import reduce
>>> data_reduce = reduce(lambda x, y: x+y, [2,4,6,8])
>>> print(data_reduce)
20

การใชงาน reduce( ) จะอานตัวแปรในรายการทีละ 2 ตัว โดยเริ่มจากสองตัวแรก เพื่อดําเนินการตามฟงกชัน หรือ


แลมบดา เมื่อดําเนินการเสร็จ ก็จะอาน รายการตัวที่ 3 เพื่อกําเนินการตอไป และดําเนินการตอไปเรื่องๆ จนหมดรายการ
การดําเนินการอยางยอจะยังมีอีกไหมที่ใชงานแทนคําสั่ง reduce( ) อยางกรณีการบวกรวม หากคิดยอนถึงฟงกชัน
พื้นฐาน เชน sum( ), max( ) ก็นาจะแทนได เชน:

Code 16.
>>> sum([2,4,6])
12
>>> max([2,4,6])
6

ตามตัวอยางที่ยกมานี้ เปนแบบนี้หรือเปลา ที่ฟงกชัน reduce( ) ไมไดนํามารวมกับ Python 3 หรือวาตัวอยางนี้


ดูงายไปที่บังเอิญมีฟงกชัน sum( ) ใหใชงาน ลองนึกถึงตัวอยางที่ยากกวานี้
เพื่อใหการทํางานซับซอนขึ้น เชน ถาตองการใหคูณ คารวมทุกตัวใน list แตเลือกเฉพาะ คาที่เปนเลขคู จะเขียนรวม
การทํางานของ reduce และ filter โดย filter กรองเฉพาะขอมูลที่เปนเลขคู สงเปน list ให reduce( ) คูณคารวม จะเขียน
ไดวา

Code 17.
>>> nums = [1,2,3,4,5]
>>> sum_sqr = reduce(lambda x,y: x*y, filter(lambda x: x%2==0, nums))
>>> sum_sqr
8

แบบฝกหัด
1. จาก [1, 3, 5, 7] จงแปลงใหเปนเลข ผลบวกของขอมูล แตละคู ซึ่งผลลัพธ คือ [4, 12]
2. จาก คลาส Product ที่ประกอบดวยสมาชิก id, name, price ใหสรางเปน ออบเจ็กต 4 ตัว ที่มี id, name, price
ตางกัน เก็บใน list แลวทําการแปลง list นี้ ใหมี ราคาเพิ่มขึ้น 7%

เอกสารประกอบการสอน การเขียนโปรแกรมดวยภาษา Python วิทยาลัยเซาธอีสบางกอก 5


3. จาก list ในขอ 2 ใหทําการแปลงขอมูลใหอยูในรูป dict จากใชฟงกชัน map( )

แหลงขอมูลนาอาน
Joe James. Python: Lambda, Map, Filter, Reduce Functions.
https://www.youtube.com/watch?v=cKlnR-CB3tk.(27 August 2019).
Kite. Best Practices for Using Functional Programming in Python.
https://kite.com/blog/python/functional-programming. (27 August 2019).

เอกสารประกอบการสอน การเขียนโปรแกรมดวยภาษา Python วิทยาลัยเซาธอีสบางกอก 6

You might also like