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 แทน