#!/usr/bin/env python
# coding: utf-8
# # วิธีทำงานโดยเปิดไฟล์แล้วอ่านทีละบรรทัด (ตอน 2)
# เราสามารถใช้วิธี:
# ```python
# inputfile = open(filename)
# for line in inputfile:
# work_on_the_line
# ```
# เช่นโค้ดข้างล่างเปิดไฟล์ `/usr/share/dict/words` แล้วอ่านทีละบรรทัด โดยที่แต่ละบรรทัดอยู่ในตัวแปร `word` ด้วยคำสั่ง `for word in inputfile:`
#
#
# ### ตัวอย่าง: หาคำที่เป็น Palindrome (คำที่กลับหน้าหลังแล้วเหมือนเดิม)
#
# In[1]:
#หาคำที่เป็น palindrome (คำที่กลับหน้าหลังแล้วเหมือนเดิม)
inputfile = open('/usr/share/dict/words') #เปิดไฟล์ที่มีคำภาษาอังกฤษบรรทัดละหนึ่งคำ
for word in inputfile: #อ่านเข้ามาทีละบรรทัด เก็บบรรทัดไว้ในตัวแปร word
word = word.strip() #strip() จะลบตัวอักษรที่มองไม่เห็น (white spaces) ด้านหน้าและด้านหลังของคำ รวมถึงตัวอักษรขึ้นบรรทัดใหม่ (newline, \n)
if len(word) <= 2: #ถ้าคำยาวไม่เกิน 2 ตัวอักษร เราจะไม่นับมันเป็น palindrome
continue
if word == word[::-1]: #word[::-1] หมายถึงการกลับหลังมาหน้า ดูส่วน "slices" ที่ https://snakify.org/en/lessons/lists/
print(word)
# ### ตัวอย่าง: หาคำที่ยาวที่สุด
#
#
# In[2]:
inputfile = open('/usr/share/dict/words')
max_word = "" #คำที่ยาวที่สุดที่เราเคยเห็น เนื่องจากตอนนี้ยังไม่เห็นสักคำ มันจึงเป็นคำว่างๆไม่มีตัวอักษรอะไร
for word in inputfile:
word = word.strip()
if len(word) > len(max_word): #ถ้าคำที่พึ่งอ่านเข้ามายาวกว่าคำที่ยาวที่สุดที่เราเคยเห็น...
max_word = word #...เราก็เปลี่ยนคำที่ยาวทีสุดที่เราเคยเห็นเป็นคำนี้
print(max_word, len(max_word)) #len(x) คือความยาวของ x ว่ามีกี่ตัวอักษร นอกจากนี้ len ยังใช้บอกจำนวนของใน list, dictionary, ฯลฯ ด้วย
# เนื่องจากในโค้ดข้างบน เราเปรียบเทียบแบบ if len(word) > len(max_word):
คือถ้าคำมีความยาวเท่าๆกัน เราจะจำเฉพาะคำแรกเท่านั้น เพราะเราจะเปลี่ยนคำที่จำก็ต่อเมื่อคำใหม่มีความยาวมากกว่าคำเก่า ถ้าจะหาคำทุกคำที่มีความยาว 24 ตัวอักษรเราก็สามารถหาแบบนี้ตรงๆได้:
# In[3]:
inputfile = open('/usr/share/dict/words')
for word in inputfile:
word = word.strip()
if len(word) == 24: #ดูเฉพาะคำที่มี 24 ตัวอักษร
print(word, len(word))
# บางทีเราอาจจะสนใจคำที่ยาวๆโดยไม่จำเป็นต้องยาวที่สุด เช่นถ้าอยากเห็นคำที่ยาวตั้งแต่ 20 ตัวอักษรขึ้นไปเราก็อาจทำอย่างนี้ได้:
# In[4]:
inputfile = open('/usr/share/dict/words')
long_words = [] #สร้าง list ชื่อ long_words เพื่อเก็บคำยาวๆหลายๆคำ ถ้าไม่คุ้นเคยให้อ่านที่ https://snakify.org/en/lessons/lists/
for word in inputfile:
word = word.strip()
if len(word) >= 20: #ถ้าคำมี 20 ตัวอักษรขึ้นไป...
long_words.append(word) #...ให้เอาคำนั้นไปใส่เพิ่มใน list ที่ชื่อ long_words
print(long_words)
# ถ้าเราอยากรู้ว่าคำที่มีตัวอักษร 1, 2, 3,..., 24 ตัว มีอย่างละกี่คำเราก็อาจทำตรงๆอย่างนี้ได้ แบบนี้จะมีการอ่านไฟล์ 24 ครั้ง:
# In[5]:
print("#letters\t#words") #พิมพ์่ชื่อคอลัมน์ให้คนอ่าน
for letters in range(1,25): #letters คือจำนวนตัวอักษร เริ่มจาก 1 ไปถึง 25-1 = 24 เพราะเรารู้ว่าคำยาวสุดมี 24 อักษร
count = 0 #จำนวนคำที่มี "letters" ตัวอักษร
inputfile = open('/usr/share/dict/words') #อ่านรายการคำ หนึ่งบรรทัดมีหนึ่งคำ
for word in inputfile: #อ่านไปทีละบรรทัด
word = word.strip() #ลบตัวขึ้นบรรทัดใหม่ (\n หรือ new line)
if word[0] in "abcdefghijklmnopqrstuvwxyz": #ดูเฉพาะคำที่ขึ้นต้นด้วยอักษรตัวเล็กเท่านั้น ไม่ดูพวกชื่อเฉพาะ
if len(word) == letters: #ดูเฉพาะคำที่มีตัวอักษร letters ตัว แล้วเพิ่มจำนวนใน count
count = count + 1
print(f"{letters}\t\t{count}") #แสดงผลด้วย f-string (ดู #3 ที่ https://realpython.com/python-string-formatting/)
# ### ตัวอย่างฟังก์ชั่น
# ฟังก์ชั่นจะทำหน้าที่ทำนองเดียวกับ Blocks ใน Scratch ถ้ายังไม่คุ้นเคยให้ไปดู[ที่นี่](https://snakify.org/en/lessons/functions)
#
# เราจะป้อนข้อมูล input เข้าไป แล้่วมันจะทำงานหรือสร้าง output ให้เรา
#
# ถ้าเราต้องทำอะไรยุ่งๆหรือซ้ำๆเราควรจะจัดรูปมันเป็นฟังก์ชั่นเสีย โปรแกรมเราจะได้อ่านง่ายๆ
#
# ดูตัวอย่างสองสามอันนี้เป็นไอเดีย
#
# In[6]:
def double(x):
"รับค่า x เข้าไปแล้วคำนวณค่า 2*x ให้"
return(2*x)
# In[7]:
def is_even(x):
"ดูว่า x เป็นเลขคู่หรือไม่"
if x % 2 == 0: #ถ้าเศษจากการหารด้วย 2 เป็น 0 ก็แสดงว่าเป็นเลขคู่
return(True)
else:
return(False)
# In[8]:
def starts_with_small_letter(word):
"ดูว่าตัวอักษรแรกใน word เป็นอักษรตัวเล็กหรือไม่"
small_letters = "abcdefghijklmnopqrstuvwxyz"
if word[0] in small_letters:
return(True)
else:
return(False) #ถ้าตัวแรกไม่อยู่ใน a-z เราก็ถือว่าคำนั้นไม่ได้ขึ้นต้นด้วยอักษรตัวเล็ก
# In[9]:
def number_of_words_with_length(n, list_of_words):
"ดูคำในไฟล์ list_of_words ว่ามีกี่คำที่มี n ตัวอักษร"
inputfile = open(list_of_words)
count = 0
for word in inputfile:
word = word.strip()
if starts_with_small_letter(word):
if len(word) == n:
count = count + 1
return(count)
# In[10]:
double(100) #ควรคำนวณออกมาเป็น 200
# In[11]:
is_even(15) #ควรเป็น False เพราะ 15 ไม่ใช่เลขคู่
# In[12]:
starts_with_small_letter("kangaroo") #ควรเป็น True เพราะ "kangaroo" ขึ้นต้นด้วยอักษรตัวเล็ก
# In[13]:
number_of_words_with_length(11, "/usr/share/dict/words") #ควรเป็น 23773 เมื่อเทียบกับด้านบน
# ลองนับจำนวนคำที่มีตัวอักษรตั้งแต่ 1, 2, 3, ..., 24 อีกที โดยใช้ฟังก์ชั่น number_of_words_with_length()
ด้านบน
#
# ทำแบบนี้โค้ดจะดูสั้นลง แต่ก็ยังอ่านไฟล์หลายรอบเหมือนกัน เราสามารถเขียนโค้ดให้อ่านไฟล์ครั้งเดียวแล้วทำอะไรให้เสร็จไปเลยดังที่จะเขียนต่อไปด้านล่าง
# In[14]:
#โค้ดดูสั้นลง แต่อ่านไฟล์ 24 ครั้งเหมือนเดิม เพราะทุกครั้งที่ฟังก์ชั่น number_of_words_with_length ทำงานจะมีการอ่านไฟล์ 1 ครั้ง
print("#letters\t#words")
for letters in range(1,25):
count = number_of_words_with_length(letters, "/usr/share/dict/words")
print(f"{letters}\t\t{count}")
# ตัวอย่างนับคำที่ความยาวต่างๆโดยอ่านไฟล์ครั้งเดียว
# In[15]:
"""
อ่านไฟล์ครั้งเดียว เก็บจำนวนคำที่มีความยาว n อักษรไว้ใน count[n]
count ต้องยาว 25 แทนที่จะเป็น 24 เพราะเราต้องการ count[24] ด้วยเพราะคำที่ยาวที่สุดยาว 24 ตัวอักษร
ทำแบบนี้เร็วกว่าแบบข้างบนที่อ่านไฟล์ 24 ครั้ง
"""
print("#letters\t#words")
count = [0] * 25 #count เป็น list = [0, 0, 0, ..., 0] มี 0 25ตัว
inputfile = open('/usr/share/dict/words')
for word in inputfile:
word = word.strip()
if starts_with_small_letter(word):
count[len(word)] += 1
for length in range(1,25):
print(f"{length}\t\t{count[length]}")
# เราสามารถเอาจำนวนคำใน count[]
มาวาดกราฟได้ด้วย matplotlib ดังนี้ จะเห็นว่าคำยาว 9 ตัวอักษรมีจำนวนมากที่สุด:
# In[16]:
get_ipython().run_line_magic('matplotlib', 'inline')
import matplotlib.pyplot as plt
lengths = range(1,25) #ความยาวคำตั้งแต่ 1 ถึง 24 ตัวอักษร
numwords = count[1:] #count[]เก็บจำนวนคำที่มีความยาว n อักษรไว้ใน count[n]
plt.bar(lengths, numwords, align='center', alpha=0.5)
plt.xticks(lengths, lengths)
plt.title('Number of words vs. word length')
plt.xlabel('Word length in characters')
plt.ylabel('Number of words')
plt.show()
# In[ ]: