เฉลยโจทย์: การประมวลผลข้อมูลจากไฟล์#
โจทย์การเขียนเรกเอกซ์#
ข้อ 1: ทะเบียนรถ#
เรกเอกซ์:
[A-Z]{2}\d{3,4}
คำอธิบาย:
^[A-Z]{2}
: ขึ้นต้นด้วยอักษรภาษาอังกฤษตัวพิมพ์ใหญ่ 2 ตัว\d{3,4}
: ตามด้วยตัวเลข 3 หรือ 4 ตัว
ข้อ 2: รหัสสีแบบ 6 หลักในระบบฐานสิบหก#
เรกเอกซ์:
#[0-9a-fA-F]{6}
คำอธิบาย:
[0-9a-fA-F]{6}
: ตามด้วยตัวเลข 0-9 หรือ a-f หรือ A-F จำนวน 6 ตัว
ข้อ 3: ชื่อคนไทยที่ประกอบด้วยตัวอักษรไทยเท่านั้น#
เรกเอกซ์:
[ก-์]{2,}
คำอธิบาย:
^[ก-์]{2,}
: ต้องมีตัวอักษรไทย 2 ตัวหรือมากกว่า
ข้อ 4 ชื่อผู้ใช้งาน#
เรกเอกซ์:
[a-z][a-z0-9_.]*[a-z0-9]
คำอธิบาย:
[a-z]
: ต้องขึ้นต้นด้วยอักษรภาษาอังกฤษตัวพิมพ์เล็ก[a-z0-9_.]*
: ประกอบด้วยอักษรภาษาอังกฤษตัวพิมพ์เล็ก ตัวเลข และเครื่องหมาย _ หรือ . ได้หลายตัว[a-z]
: ลงท้ายด้วยอักษรภาษาอังกฤษตัวพิมพ์เล็ก หรือตัวเลข
ข้อ 5 เบอร์โทรศัพท์ไทย#
เรกเอกซ์:
0\d{9}
คำอธิบาย:
^0
: ขึ้นต้นด้วยเลข 0\d{9}
: ตามด้วยตัวเลข 9 ตัว
ข้อ 6 ที่อยู่#
เรกเอกซ์:
[ก-ฮ0-9/ ]+
คำอธิบาย:
^[ก-ฮ0-9/]+
: ต้องประกอบด้วยตัวอักษรไทย ตัวเลข และเครื่องหมาย / อย่างน้อยหนึ่งตัว
ข้อ 7 สกุลไฟล์#
เรกเอกซ์:
[a-zA-Z].*\.((txt)|(csv)|(json))$
คำอธิบาย:
[a-zA-Z]
: ต้องขึ้นต้นด้วยตัวอักษรภาษาอังกฤษตัวเล็กหรือตัวใหญ่.*
: แทนตัวอักษรใดก็ได้ 0 ตัวหรือมากกว่า\.((txt)|(csv)|(json))
: นามสกุลไฟล์ต้องเป็น .txt, .csv หรือ .json
ข้อ 8 อีเมลล์#
เรกเอกซ์:
[a-zA-Z0-9]+@(gmail|yahoo)\.com
คำอธิบาย:
[a-zA-Z0-9]+
: ขึ้นต้นด้วยตัวอักษร ตัวเลข อย่างน้อย 1 ตัว@(gmail|yahoo)\.com
: ลงท้ายด้วย @gmail.com หรือ @yahoo.com
ข้อ 9 วันเดือน#
เรกเอกซ์:
^(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[0-2])$
คำอธิบาย:
^(0[1-9]|[12][0-9]|3[01])
: วันที่ต้องอยู่ระหว่าง 01-09 หรือ 10-29 หรือ 30-31/(0[1-9]|1[0-2])
: เดือนต้องอยู่ระหว่าง 01-09 หรือ 10-12
ข้อ 10 ขึ้นต้นอะไรก็ได้แต่ต้องลงท้ายด้วยสระ า#
เรกเอกซ์:
([ก-์]*[^เ ][ก-ฮ][่-๋]?า)|([ก-ฮ][่-๋]?า)
คำอธิบาย: แบ่งเป็นสองส่วนหลัก โดยใช้ตัวแบ่งคือ
|
ส่วนแรก:
([ก-์]*[^เ ][ก-ฮ][่-๋]?า)
เพื่อจับคำที่มีหลายพยางค์([ก-์]*)
: จับคู่ตัวอักษรไทยตั้งแต่ตัวใดตัวหนึ่งไปจนถึงตัว “์” (ไม้ไต่คู้) หรืออักษรใดๆ ในช่วงนี้ ได้ตั้งแต่ 0 ตัวขึ้นไป[^เ ]
: ต้องไม่ใช่สระ “เ” หรือช่องว่าง ( ) ตัวนี้ใช้เพื่อป้องกันการจับคู่คำที่มี “เ” นำหน้า เช่น “เกา” ไม่ให้ถูกจับคู่[ก-ฮ]
: จับคู่ตัวอักษรไทยในช่วงตั้งแต่ “ก” ถึง “ฮ” ที่ตามหลังตัวที่ไม่ใช่ “เ”[่-๋]?
: จับคู่รูปวรรณยุกต์ไทย เช่น ไม้เอก ไม้โท เป็นต้น แต่มีหรือไม่มีก็ได้า
: จับคู่สระ “า” ซึ่งเป็นตัวอักษรสุดท้ายของคำ
ส่วนที่สอง:
([ก-ฮ][่-๋]?า)
เพื่อจับคำพยางค์เดียวที่ออกเสียงเป็น “า”[ก-ฮ]
: จับคู่ตัวอักษรไทยตั้งแต่ “ก” ถึง “ฮ”[่-๋]?
: จับคู่รูปวรรณยุกต์ไทย (ไม้เอก, ไม้โท, ฯลฯ) มีหรือไม่มีก็ได้า
: จับคู่สระ “า” เป็นตัวสุดท้ายของคำ
โจทย์ปัญหาการประมวลผลข้อมูลจากไฟล์#
ข้อ 1#
import re
from collections import Counter
# สร้าง Counter เพื่อเก็บค่า part-of-speech tags และคำ
pos_counter = Counter()
word_counter = Counter()
# กำหนดรูปแบบ regex เพื่อค้นหาคำและ part-of-speech tags
pattern = r'(\S+?)_([A-Za-z$]+)'
# เปิดไฟล์และอ่านไฟล์ทีละบรรทัด
with open('obama.txt', 'r', encoding='utf-8') as file:
for line in file:
# ค้นหาคำทั้งหมดที่ตรงกับ pattern ในบรรทัดปัจจุบัน
matches = re.findall(pattern, line)
# อัพเดต Counter ด้วยค่าที่พบ
pos_counter.update(pos for word, pos in matches)
word_counter.update(word for word, pos in matches)
# ดึงข้อมูล part-of-speech tags ที่มีความถี่สูงสุดและคำ 100 คำแรก
pos_freq = pos_counter.most_common()
top_100_word = word_counter.most_common(100)
# แสดงผลลัพธ์
print("\nความถี่ของ Part-of-Speech Tags:")
for pos, freq in pos_freq:
print(f"{pos}: {freq}")
print("\nคำ 100 คำแรกที่มีความถี่สูงสุด:")
for word, freq in top_100_word:
print(f"{word}: {freq}")
ข้อ 2#
ข้อ 2.1#
import re
def is_name_like(word):
pattern = r'^[A-Z][a-z]*$'
# ใช้ re.match เพื่อตรวจสอบว่าคำตรงกับแพตเทิร์นหรือไม่ และแปลงผลลัพธ์เป็นบูลีน
return bool(re.match(pattern, word))
ข้อ 2.2#
def get_all_names(sentence):
pattern = r'\b[A-Z][a-z]*\b'
# ใช้ re.findall เพื่อค้นหาคำทั้งหมดที่ตรงกับ pattern ในประโยค
names = re.findall(pattern, sentence)
return names
ข้อ 2.3#
def censor_names(sentence):
pattern = r'\b[A-Z][a-z]*\b'
# ใช้ re.sub เพื่อแทนที่คำที่ตรงกับ pattern ด้วย "XXX"
censored_sentence = re.sub(pattern, 'XXX', sentence)
return censored_sentence
ข้อ 3#
def autoanswer(question):
# ตรวจสอบว่าประโยคขึ้นต้นด้วย "Do" หรือ "Does" หรือไม่
match = re.match(r'^(Do|Does) (.*)', question)
if match:
# ถ้าเป็นประโยคคำถามที่ขึ้นต้นด้วย "Do" หรือ "Does"
verb = match.group(1)
rest_of_sentence = match.group(2)
# แทนที่ "Do" หรือ "Does" ด้วย "do" หรือ "does" ตามลำดับ
response_verb = "do" if verb == "Do" else "does"
# สร้างคำตอบในรูปแบบ "Yes, ... do/does ..."
return f"Yes, {rest_of_sentence.split()[0]} {response_verb} {rest_of_sentence[len(rest_of_sentence.split()[0])+1:]}."
else:
# ถ้าไม่ใช่ประโยคคำถามที่ขึ้นต้นด้วย "Do" หรือ "Does"
return f"{question}?"
ข้อ 4#
ข้อ 4.1#
import re
# อ่านไฟล์ nyt_eng_200001
with open('small_nyt_eng_200001', 'r') as file:
s = file.read()
# หาคำที่ขึ้นต้นด้วยตัว k
pattern_start_k = r'\bk\w*'
start_k_words = re.findall(pattern_start_k, s)
# หาคำที่ตัวที่สองเป็นตัว k
pattern_second_k = r'\b\w*k\w*'
second_k_words = re.findall(pattern_second_k, s)
# หาคำที่ลงท้ายด้วยตัว k
pattern_end_k = r'\b\w*k\b'
end_k_words = re.findall(pattern_end_k, s)
# นับจำนวนคำที่ตรงกับแต่ละ pattern
total_words = len(start_k_words) + len(second_k_words) + len(end_k_words)
# แสดงผลลัพธ์
print("จำนวนคำที่ขึ้นต้นด้วยตัว k:", len(start_k_words))
print("จำนวนคำที่ตัวที่สองเป็นตัว k:", len(second_k_words))
print("จำนวนคำที่ลงท้ายด้วยตัว k:", len(end_k_words))
print("จำนวนคำที่มีคุณสมบัติตรงตามที่กำหนดทั้งหมด:", total_words)
ข้อ 4.2#
import re
# อ่านไฟล์ nyt_eng_200001
with open('small_nyt_eng_200001', 'r') as file:
s = file.read()
# หาคำที่ขึ้นต้นด้วยตัว k
pattern_start_k = r'\bk\w*'
start_k_words = set(re.findall(pattern_start_k, s))
# หาคำที่ตัวที่สองเป็นตัว k
pattern_second_k = r'\b\w{k}\w*'
second_k_words = set(re.findall(pattern_second_k, s))
# หาคำที่ลงท้ายด้วยตัว k
pattern_end_k = r'\b\w*k\b'
end_k_words = set(re.findall(pattern_end_k, s))
# รวมคำที่ไม่ซ้ำจากทั้งสามชุด
all_k_words = start_k_words.union(second_k_words).union(end_k_words)
# นับจำนวนคำที่ไม่ซ้ำกัน
total_unique_words = len(all_k_words)
# แสดงผลลัพธ์
print("จำนวนคำที่ขึ้นต้นด้วยตัว k (ไม่ซ้ำ):", len(start_k_words))
print("จำนวนคำที่ตัวที่สองเป็นตัว k (ไม่ซ้ำ):", len(second_k_words))
print("จำนวนคำที่ลงท้ายด้วยตัว k (ไม่ซ้ำ):", len(end_k_words))
print("จำนวนคำที่มีคุณสมบัติตรงตามที่กำหนดทั้งหมด (ไม่ซ้ำ):", total_unique_words)
ข้อ 5#
import re
def find_names(announcement_file):
# เปิดไฟล์ประกาศเพื่ออ่านข้อมูล
with open(announcement_file, 'r', encoding='utf-8') as file:
text = file.read()
# กำหนด pattern ของ regex เพื่อจับชื่อในวงเล็บที่มีคำนำหน้าว่า นาย นางสาว หรือ นาง
pattern = r'\((นาย|นางสาว|นาง)(\S+)'
# ใช้ re.findall เพื่อหาข้อความทั้งหมดที่ตรงกับ pattern ใน text
# re.findall จะคืนค่าเป็นลิสต์ของ tuple ที่แต่ละ tuple มีสองส่วนคือคำนำหน้าและชื่อ
matches = re.findall(pattern, text)
# สร้างลิสต์เปล่าเพื่อเก็บชื่อผู้ชายและผู้หญิง
male_names = []
female_names = []
# ลูปผ่านผลลัพธ์ที่จับได้จาก regex
for title, name in matches:
# ถ้าคำนำหน้าเป็น "นาย" ให้เพิ่มชื่อไปยังลิสต์ male_names
if title == "นาย":
male_names.append(name)
# ถ้าคำนำหน้าเป็น "นางสาว" หรือ "นาง" ให้เพิ่มชื่อไปยังลิสต์ female_names
else:
female_names.append(name)
# คืนค่าลิสต์ชื่อผู้ชายและผู้หญิง
return male_names, female_names
ข้อ 6#
# import โมดูล regular expression เพื่อใช้ในการหาคำ
import re
def count_en_th_words(word_list):
"""
Example:
>>> count_en_th_words(['รองเท้า', 'ไม่', 'match', 'กับ', 'coat', 'เลย'])
{'en': 2, 'th': 4}
"""
# สร้าง dict ที่มีค่าเริ่มต้นของจำนวนคำภาษาอังกฤษและภาษาไทยเป็น 0
result_dict = {'en': 0, 'th': 0}
# วนลูปผ่านคำในรายการคำ
for w in word_list:
# ตรวจสอบว่าคำเป็นภาษาอังกฤษหรือไม่
if re.search('[a-zA-Z]', w):
# ถ้าใช่ เพิ่มจำนวนคำภาษาอังกฤษขึ้น 1
result_dict['en'] += 1
else:
# ถ้าไม่ใช่ เพิ่มจำนวนคำภาษาไทยขึ้น 1
result_dict['th'] += 1
return result_dict