วันอังคารที่ 8 เมษายน พ.ศ. 2568

Python map(), filter() vs comprehensions และ lambda

    หลังจากที่เรารู้จัก List Comprehensions & Dictionary Comprehensions  ต่อมาเรามารู้จักอีก 2 คำสั่งที่ให้ผลคล้ายๆกัน คือ map และ filter 


เอาจริงๆก็ผมไม่ได้ใช้ 2 function นี้นะ แต่เค้าบอกให้เรียนก็เรียนๆไป คิดว่าน่าจะได้ใช้แหละ


มาดูความหมายและวิธีใช้งานกัน

map(function, iterable) ใช้สำหรับแปลงข้อมูลใน iterable ทุกตัว โดยใช้ function

filter(function, iterable) ใช้คัดกรองเฉพาะค่าที่ function คืนค่าเป็น True

 iterable หมายถึงตัวแปรหรือ object ที่สามารถ loop ได้นะครับ


map  

    การใช้ map จะต้องมี function กับ iterable ไว้ loop นะครับ โดยที่การทำงานจะประมาณว่า loop ข้อมูล แล้วแปลงค่าผ่าน function แล้วเอาค่าที่ return จาก function นั้นมาแทนที่

เริ่มจากเราต้องมี function ก่อน เพื่อให้ map ใช้ในการแปลงค่า ในตัวอย่างนี้ ให้เป็น function หาพื้นที่สี่เหลี่ยมจตุรัส เอาจริงๆก็ function ยกกำลัง 2 แหละ

ต่อมาเราต้องมี ข้อมูลอะไรสักอย่างที่มัน loop ได้ ตัวอย่างนี้เรามี list ความยาวด้านอยู่

list_length = [1,2,3,4]

def square_area(length: int) -> int:
    return length*length

list_square_area = list(map(square_area,list_length))


ไปลองมา เหมือนต้องใส่ list ครอบด้วย เพราะ function map จะ return มาเป็น object map

ครับ แล้วเราก็ได้ function การแปลงค่ามา ซึ่งถ้าเอาไปเทียบกับ list comprehension มันก็จะประมาณนี้

list_length = [1,2,3,4]
list_square_area = [_*_ for _ in list_lange]

# or
list_length = [1,2,3,4]
def square_area(length: int) -> int:
    return length*length

list_square_area = [square_area(_) for _ in list_length]


หรือถ้าเป็นแบบเต็มๆก็

list_length = [1,2,3,4]
list_square_area = []

for length in list_length:
    square_area = length*length
    list_square_area.append(square_area)

# or
list_length = [1,2,3,4]
list_square_area = []

def square_area(length: int) -> int:
    return length*length

for length in list_length:
    area = square_area(length)
    list_square_area.append(area)


ก็จะประมาณนี้แหละครับ


filter

    ต่อมาเป็นคิวของคำสั่ง filter  ตัวนี้ทำงานคล้ายกับคำสั่ง map ครับ แต่เปลี่ยนจาก เอาค่าที่ได้จาก function มา replace เป็นใช้ function ในการเช็กว่าค่านี้จะเอาป่าว ถ้า function return เป็น True ก็จะเก็บไว้ แต่ถ้าเป็น False ก็ทิ้งไป ตัวนี้ไม่เอา จบเท่านี้เลยครับ


จากที่อ่านผมก็มีคำถามว่า แล้วจะมี map กับ filter ไว้ทำไม คำตอบที่ผมได้มาคือ

    map() กับ filter() ว่า “ไม่จำเป็นต้องสร้าง list ทันที” เพราะทั้งคู่จะคืนค่าเป็น iterator แบบ lazy evaluation นั่นแปลว่า มันจะยังไม่คำนวณอะไรเลย จนกว่าจะมีคนไปดึงข้อมูลออกมาใช้จริงๆ เช่นแปลงเป็น list หรือเข้าไป loop อ่านค่าจากตัวมัน และ ถ้ามีข้อมูลเป็นล้านรายการ มันจะประหยัด memory มาก เพราะไม่โหลดทั้งหมดเข้าหน่วยความจำ


map() กับ filter() นิยมใช้ร่วมกับ lambda 

lambda คืออะไร?

lambda คือ ฟังก์ชันแบบย่อ (anonymous function)
ไม่มีชื่อเหมือนฟังก์ชันปกติ (def) และเขียนได้ในบรรทัดเดียว

รูปแบบการเขียน:


lambda arguments: expression

  • arguments → ตัวแปรรับค่า

  • expression → นิพจน์ที่คืนค่ากลับ (return โดยอัตโนมัติ)

  • ไม่มีคำว่า return


ถ้าให้อธิบายแบบภาษาที่ผมเข้าใจก็ประมาณว่า
ใช้คำสั่ง lambda แล้วก็ตามด้วยชื่อตัวแปร อะไรก็ได้ ใส่ๆไปเลย คั่นด้วย : ทีนึง 
จากนั้นก็ใส่ expression หรือ process ที่อยากให้ function ทำงาน 
ซึ่งข้อจำกัดคือ ใส่ได้แค่ expression เดียว ต่อให้ใส่ได้ก็ไม่ควร อ่านยาก



ตัวอย่าง map ด้านบน

list_length = [1,2,3,4]

def square_area(length: int) -> int:
    return length*length

list_square_area = list(map(square_area,list_length))


นำมาเขียนใหม่เป็น lambda ได้แบบนี้

list_length = [1,2,3,4]

list_square_area = list(map(lambda length: length*length, list_length))



หน้าแบบที่เค้านิยมกันก็

list_length = [1,2,3,4]

list_square_area = list(map(lambda i: i ** 2, list_length))




ไม่มีความคิดเห็น:

แสดงความคิดเห็น