Comprehension#

ก่อนหน้านี้เราได้เรียนวิธีการสร้างลิสต์ ดิกต์ และเซ็ตด้วยวิธีการดังนี้

my_list = list()
my_list2 = []
my_dict = dict()
my_dict2 = {}
my_set = set()
my_set = set(my_list)

List comprehension#

List comprehension คือสร้างลิสต์ขึ้นมาจากสิ่งที่เป็น iterable เช่น ลิสต์ ดิกชันนารี และเซ็ต ซึ่งเป็นกรณีการใช้ที่เกิดขึ้นบ่อย เนื่องจากมีหลายครั้งที่เราต้องแปลงจากลิสต์เป็นอีกลิสต์หนึ่งซึ่งสมาชิกข้างในถูกแปลงให้เป็นอย่างหนึ่ง

ตัวอย่าง#

สมมติว่าเรามีลิสต์ของสตริง แต่เราต้องการเปลี่ยนให้เป็นตัวใหญ่ทั้งหมด เราสามารถสร้างลิสต์ใหม่เตรียมไว้รับ output จากนั้นทำการวนลูปบนสมาชิกของลิสต์ แปลงเป็นตัวใหญ่ จากนั้นก็ .append เข้าสู่ลิสต์ที่จะเป็น output ดังนี้

sentence = ['programming', 'is', 'very', 'interesting']
new_sentence = []
for w in sentence:
    new_sentence.append(w.upper())
print (new_sentence)
['PROGRAMMING', 'IS', 'VERY', 'INTERESTING']

เราสามารถเขียนให้กระชับได้โดยการใช้ list comprehension ดังนี้

sentence = ['programming', 'is', 'very', 'interesting']
new_sentence2 =[w.upper() for w in sentence]
print(new_sentence2)
['PROGRAMMING', 'IS', 'VERY', 'INTERESTING']

ตัวอย่าง#

สมมติว่าเราต้องการเปลี่ยนให้จากลิสต์เดิมให้เป็นลิสต์ที่มีความยาวของสตริงแต่ละตัวแทน เราสามารถทำด้วยวิธีที่คล้ายคลึงกัน

sentence = ['programming', 'is', 'very', 'interesting']
length_list = []
for w in sentence:
    length_list.append(len(w))
print (length_list)
[11, 2, 4, 11]

เราสามารถเขียนให้กระชับได้โดยการใช้ list comprehension ดังนี้

sentence = ['programming', 'is', 'very', 'interesting']
length_list = [len(w) for w in sentence] 
print(length_list)
[11, 2, 4, 11]

วิธีการใช้ list comprehension มีดังนี้ [expression for ตัวแปร in iterable] เช่น

  • [w.upper() for w in sentence]

  • [len(w) for w in sentence]

Comprehension แบบมีเงื่อนไข#

เราสามารถระบุเพิ่มเติมได้ด้วยว่าสมาชิกตัวไหนบ้างใน iterable ที่เป็น input จะถูกรวมไว้ในลิสต์ output

ตัวอย่าง#

สมมติว่าเราอยากแปลงลิสต์ที่มีคำในประโยคมาเป็นลิสต์ที่มีความยาวของแต่ละคำในประโยคอยู่ โดยที่เราสนใจเฉพาะคำที่มีความยาวมากกว่า 2 ตัวอักษร

sentence = ['programming', 'is', 'very', 'interesting']
length_list = []
for w in sentence:
    if (len(w) > 2):
        length_list.append(len(w))
print (length_list)
[11, 4, 11]

เราสามารถเขียนโค้ดให้กระชับขึ้นโดยใช้ list comprehension ได้ดังนี้

sentence = ['programming', 'is', 'very', 'interesting']
length_list = [len(w) for w in sentence if len(w) >2]
print(length_list)
[11, 4, 11]

ตัวอย่าง#

สมมติว่าเรามีลิสต์ของคำในประโยคอยู่ แต่ว่าเราอยากได้ลิสต์ที่มีคำที่เป็นตัวอักษรภาษาไทยเท่านั้น

import re
word_list = ['บท', 'นี้', 'เกี่ยวกับ', 'list', 'comprehension', 'และ', 'อื่นๆ']
new_word_list = []
for word in word_list:
    if re.match('[ก-์]+', word):
        new_word_list.append(word)
print(new_word_list)
['บท', 'นี้', 'เกี่ยวกับ', 'และ', 'อื่นๆ']

เราสามารถเขียนโค้ดให้กระชับขึ้นโดยใช้ list comprehension ได้ดังนี้

import re
word_list = ['บท', 'นี้', 'เกี่ยวกับ', 'list', 'comprehension', 'และ', 'อื่นๆ']
new_word_list = [word for word in word_list if re.match('[ก-์]+', word)]
print(new_word_list)
['บท', 'นี้', 'เกี่ยวกับ', 'และ', 'อื่นๆ']

สรุปการใช้ comprehension แบบมีเงื่อนไข#

วิธีการใช้ list comprehension แบบมีเงื่อนไข มีดังนี้ [expression for ตัวแปร in iterable if เงื่อนไข] เช่น

  • [len(w) for w in sentence if len(w) >2]

  • [word for word in word_list if re.match('[ก-์]+', word)]

Set comprehension#

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

วิธีการใช้ set comprehension เหมือน list comprehension เพียงแค่เปลี่ยนเครื่องหมาย [] เป็น {}

{expression for ตัวแปร in iterable if เงื่อนไข}

ตัวอย่าง#

Vocabulary หมายถึงเซ็ตของคำศัพท์ทั้งหมดที่เราต้องการวิเคราะห์ หรือนำมาเป็นส่วนหนึ่งของโมเดล จะนับเฉพาะคำที่รูปไม่ซ้ำกัน

สมมติว่าเรามีลิสต์ของคำทั้งหมดที่มีอยู่ในคลังข้อมูล เราต้องการทราบ vocabulary ของคลังข้อมูลนี้ว่ามีคำว่าอะไรบ้าง โดยนับเฉพาะคำที่เป็นตัวภาษาอังกฤษเท่านั้น

word_list = ['baby', 'baby', 'baby', 'oh', '...', 'baby', 'baby', 'no','!']
vocab = set()
for word in word_list:
    if word.isalpha():
        vocab.add(word)
print(vocab)
{'baby', 'oh', 'no'}

เราสามารถเขียนโค้ดให้กระชับขึ้นโดยใช้ set comprehension ได้ดังนี้

word_list = ['baby', 'baby', 'baby', 'oh', '...', 'baby', 'baby', 'no','!']
vocab2 = {word for word in word_list if word.isalpha()}
print(vocab2)
{'baby', 'oh', 'no'}

Dict comprehension#

หลักการใช้ dict comprehension ก็คล้ายคลึงกันกับ list comprehension และ set comprehension เพียงแต่ว่าเราต้องกำหนดว่า key และ value ของดิกต์ที่เราต้องการสร้างขึ้นจะต้องเป็นอะไรบ้าง

วิธีการใช้ dict comprehension มีดังนี้

{expression-key:expression-value for ตัวแปร in iterable if เงื่อนไข}

ตัวอย่าง#

สมมติว่าเรามีรายชื่อของนักเรียนอยู่ในลิสต์ และเราต้องการสร้างดิกต์ที่ key เป็นชื่อนักเรียน และ value เป็นหมายเลขกลุ่ม 1-3 เพื่อที่จะจัดนักเรียนออกเป็น 3 กลุ่ม

from random import randint
students = ['Panyut', 'Mild', 'Bew', 'Fluke', 'Paolong', 'Tangmay', 'Ya']
student_to_group = {}
for student in students:
    student_to_group[student] = randint(1,3)
print(student_to_group)
{'Panyut': 2, 'Mild': 3, 'Bew': 1, 'Fluke': 2, 'Paolong': 2, 'Tangmay': 2, 'Ya': 1}

เราสามารถเขียนโปรแกรมข้างบนให้กระชับขึ้นโดยใช้ dict comprehension ได้

students = ['Panyut', 'Mild', 'Bew', 'Fluke', 'Paolong', 'Tangmay', 'Ya']
student_to_group = {student:randint(1,3) for student in students}
print(student_to_group)
{'Panyut': 3, 'Mild': 1, 'Bew': 2, 'Fluke': 2, 'Paolong': 1, 'Tangmay': 2, 'Ya': 2}

ตัวอย่าง#

ในการสร้างโมเดลเกี่ยวกับภาษา ขั้นตอนที่จะต้องเจอบ่อย ๆ คือการแทนคำด้วยหมายเลขประจำตัว (id หรือ index) ซึ่งเราต้องกำหนดให้แต่ละคำใน vocabulary นั้นไม่ซ้ำกัน

สมมติว่าเรามีลิสต์ของคำทั้งหมดในคลังข้อมูล เราต้องการสร้างดิกที่ key เป็นคำ และ value เป็นหมายเลขประจำตัวของคำคำนั้น

word_list = ['baby', 'baby', 'baby', 'oh', '...', 'baby', 'baby', 'no','!']
word_to_index = {}
for word in word_list:
    if word not in word_to_index:
        word_to_index[word] = len(word_to_index)
print(word_to_index)
{'baby': 0, 'oh': 1, '...': 2, 'no': 3, '!': 4}

เราสามารถเขียนโดย dict comprehension ให้กระชับขึ้นดังนี้

word_list = ['baby', 'baby', 'baby', 'oh', '...', 'baby', 'baby', 'no','!']
word_set = set(word_list)
word_list = list(word_set) # ทำให้เหลือเฉพาะคำที่ไม่ซ้ำ
word_to_index = {word:index for index, word in enumerate(word_list)}
print(word_to_index)
{'...': 0, 'baby': 1, 'oh': 2, '!': 3, 'no': 4}

สรุปข้อดี ข้อเสียของการใช้ comprehension#

ข้อดีของการใช้ comprehension คือ

  • โค้ดสั้นกระชับสวยงาม ทำให้มีโอกาสเขียนโค้ดผิดน้อยลง เมื่อเทียบกับการใช้ for loop ในการแก้ปัญหาเดียวกัน

  • เร็วกว่าการใช้ for loop มาก เนื่องจากไพทอนจะทำการ optimize โค้ดให้สำหรับ comprehension

ข้อเสียของการใช้ comprehension คือ

  • ผู้ที่ไม่ได้คล่องการเขียนโค้ดด้วยภาษาไพทอนอาจจะอ่านไม่เข้าใจ เนื่องจากไม่มีภาษาคอมพิวเตอร์อื่นที่มีหรือนิยมใช้ comprehension

  • ถ้า expression ที่อยู่ใน comprehension ซับซ้อน จะทำให้อ่านได้ยาก ในกรณีนี้เราอาจจะเลี่ยงไปใช้ for loop แทน