หัดเขียนข้อมูลลงไฟล์

ปกติเวลาเราทำงานอะไรเสร็จ เราก็อยากเก็บข้อมูลไว้ ถ้าเราใช้ Python เรามีวิธีเก็บข้อมูลไว้ในไฟล์โดยการใช้ open(filename, "w") เพื่อเขียนข้อมูลลงไปในไฟล์ชื่อ filename โดยข้อมูลที่เขียนลงไปจะไปแทนที่ส่ิงที่มีอยู่ในไฟล์ filename ถ้าไฟล์นั้นมีอยู่แล้ว ถ้าใช้ open(filename, "a") ข้อมูลใหม่จะถูกเขียนต่อจากข้อมูลเก่า ดังนั้นต้องระวังให้ดีว่าต้องการจะลบล้างข้อมูลที่มีอยู่ในไฟล์ ("w" ย่อมาจาก write) หรือจะเพิ่มข้อมูลเข้าไปในไฟล์ที่มีอยู่แล้ว ("a" ย่อมาจาก append)

หลังจากเปิดไฟล์ด้วย open(...) แล้วเราก็จะใช้คำสั่ง write(...) เพื่อเขียนข้อมูลลงไปในไฟล์

ตัวอย่าง:

In [1]:
output_file = open("testoutput.txt", "w")
output_file.write("Hello, World!\n")
output_file.close()

โค้ดข้างบนจะสร้างไฟล์ชื่อ testoutput.txt ไว้ในไดเร็คทอรีปัจจุบันที่ Jupyter ใช้อยู่ ในไฟล์จะมีคำว่า Hello, World! อยู่

ตัว \n ใน output_file.write("Hello, World!\n") เรียกว่า newline หรือตัวขึ้นบรรทัดใหม่ ถ้าไม่มีเวลาเขียนข้อมูลหลายตัวด้วย write(...) หลายๆครั้งจะติดกันไปเป็นบรรทัดเดียว

เมื่อเราเขียนข้อมูลเสร็จแล้วเราจะปิดไฟล์ด้วยคำสั่ง close()

เราสามารถดูว่าไดเร็คทอรีปัจจุบันอยู่ที่ไหนโดยพิมพ์ %pwd และเปลี่ยนได้โดยพิมพ์ %cd directory_name แล้วกด Shift-Enter

เราเขียนข้อมูลหลายๆตัวได้โดยการเรียก write(...) หลายๆครั้ง:

In [2]:
output_file = open("testoutput.txt", "w")
output_file.write("1st Hello!\n")
output_file.write("2nd Hello!\n")
output_file.write("3rd Hello!\n")
output_file.close()

โค้ดข้างบนจะเขียนข้อมูลสามบรรทัดลงไปในไฟล์ testoutput.txt สังเกตว่าข้อมูลเดิม (Hello, World!) ถูกเขียนทับหายไปแล้ว ถูกแทนที่ด้วย 1st Hello!, 2nd Hello!, และ 3rd Hello! แทน ทั้งนี้เพราะว่าเมื่อเราเปิดไฟล์ testoutput.txt เราใส่ "w" เข้าไปในคำสั่ง open(...)

ถ้าเราเปิดไฟล์ testoutput.txt ดู เราจะเห็นข้อความข้างในดังนี้:

1st Hello!
2nd Hello!
3rd Hello!

ต่อไปเราจะเขียนเพิ่มข้อมูลเข้าไปในไฟล์ testoutput.txt อีก 7 บรรทัด เราต้องใช้ "a" ในคำสั่ง open(...) เพื่อจะได้เขียนต่อจากข้อมูลเดิม ไม่เขียนทับ

In [3]:
output_file = open("testoutput.txt", "a")
for i in range(4,11):
    output_file.write(str(i) + "th Hello!\n")
output_file.close()

โค้ดข้างบนใช้ for... เพื่อทำการเขียนด้วย write(...) หลายๆครั้ง

ถ้าเราเปิดไฟล์ testoutput.txt ดู เราจะเห็นข้อความข้างในดังนี้:

1st Hello!
2nd Hello!
3rd Hello!
4th Hello!
5th Hello!
6th Hello!
7th Hello!
8th Hello!
9th Hello!
10th Hello!

แบบฝึกหัด: แปลงคำต่างๆเป็นตัวเลข

อันนี้เป็นเมล์หรือไลน์ที่ชอบมีคนส่งต่อๆกันครับ:

สูตรสู่ความสำเร็จ

ถ้า A B C D E F G H I J K L M N O P Q R S T U V W X Y Z มีค่าเท่ากับ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 แล้วจะพบว่า......

1) H+A+R+D+W+O+R+K = 8+1+18+4+23+15+18+11 = 98% HARD WORK หรือ ทำงานหนัก มีค่าเท่ากับ 98 %

2) K+N+O+W+L+E+D+G+E = 11+14+15+23+12+5+4+7+5 = 96% KNOWLEDGE หรือ ความรู้ มีค่าเท่ากับ 96 %

3) L+O+V+E=12+15+22+5 = 54% LOVE หรือ ความรัก มีค่าเท่ากับ 54 %

4) L+U+C+K = 12+21+3+11 = 47% LUCK หรือ โชค มีค่าเท่ากับ 47 %

ไม่มีสิ่งใดที่มีค่า 100 % เลยหรือ !!! แล้วสิ่งใดที่มีค่าเท่ากับ 100 %

  • ใช่เงินหรือเปล่า ?……… .... .....ไม่ใช่ !!!!! (M+O+N+E+Y = 13+15+14+5+25 = 72)

  • ความเป็นผู้นำหรือเปล่า ?………ไม่ใช่ !!!!! (L+E+A+D+E+R+S+H+I+P = 12+5+1+4+5+18+19+8+9+16 = 97)

แล้วอะไรล่ะ ?

A+T+T+I+T+U+D+E = 1+20+20+9+20+21+4+5 = 100%

ATTITUDE หรือ ทัศนคติ นั่นเอง ที่มีค่าเท่ากับ 100 % ท่านคิดเช่นนั้นหรือไม่ ทุกปัญหามีทางออก . . บางทีแค่เพียงแต่เราเปลี่ยน "ทัศนคติ " ของเราเสียใหม่เท่านั้นเอง มีเพียงแต่ “ทัศนคติ” ของเราเท่านั้น ที่จะเป็นตัวนำทาง ไปสู่ความสำเร็จในชีวิต และงานที่ทำ

แบบฝึกหัดคือให้หาว่าคำภาษาอังกฤษไหนอีกบ้างที่บวกแล้วได้ 100 อีก ให้เขียนคำเหล่านั้นเก็บไว้ในสักไฟล์หนึ่ง

ตัวอย่างวิธีทำ

เราหาทางแทนค่าตัวอักษร 1 ตัวด้วยตัวเลขที่คู่กับมัน สามารถทำได้หลายทาง แบบแรกเข้าใจง่ายสุดสำหรับมือใหม่หัดเขียนโปรแกรม:

In [4]:
def char2num(c):
    """
    เปลี่ยนตัวอักษร c เป็นตัวเลข เช่น a -> 1, b -> 2, ..., z->26
    ถ้าตัวอักษร c เป็นตัวอักษรตัวใหญ่ (A, B, C,...) ให้เปลี่ยนเป็นตัวเล็กก่อนแล้วค่อยเปลี่ยนเป็นตัวเลข
    ถ้าตัวอักษร c ไม่อยู่ใน a-z ให้ตัวเลขเป็น 0
    """
    lc = c.lower() #เปลี่ยนอักษรเป็นอักษรตัวเล็กก่อน A->a, B->b, ...
    if lc == 'a':
        return(1)
    if lc == 'b':
        return(2)
    if lc == 'c':
        return(3)
    if lc == 'd':
        return(4)
    if lc == 'e':
        return(5)
    if lc == 'f':
        return(6)
    if lc == 'g':
        return(7)
    if lc == 'h':
        return(8)
    if lc == 'i':
        return(9)
    if lc == 'j':
        return(10)
    if lc == 'k':
        return(11)
    if lc == 'l':
        return(12)
    if lc == 'm':
        return(13)
    if lc == 'n':
        return(14)
    if lc == 'o':
        return(15)
    if lc == 'p':
        return(16)
    if lc == 'q':
        return(17)
    if lc == 'r':
        return(18)
    if lc == 's':
        return(19)
    if lc == 't':
        return(20)
    if lc == 'u':
        return(21)
    if lc == 'v':
        return(22)
    if lc == 'w':
        return(23)
    if lc == 'x':
        return(24)
    if lc == 'y':
        return(25)
    if lc == 'z':
        return(26)
    return(0) #ถ้าตัวอักษรไม่่อยู่ใน a-z ให้ค่าเป็น 0
In [5]:
#ทดลองหาค่าของ a, b, x, z, % ควรได้ค่าเป็น 1, 2, 24, 26, 0
print(char2num('a'))
print(char2num('b'))
print(char2num('x'))
print(char2num('z'))
print(char2num('%'))
1
2
24
26
0
In [6]:
#พิมพ์คู่ลำดับตัวอักษรและตัวเลข
for i in "abcdefghijklmnopqrstuvwxyz":
    print(f"({i}, {char2num(i)}) ", end="")
(a, 1) (b, 2) (c, 3) (d, 4) (e, 5) (f, 6) (g, 7) (h, 8) (i, 9) (j, 10) (k, 11) (l, 12) (m, 13) (n, 14) (o, 15) (p, 16) (q, 17) (r, 18) (s, 19) (t, 20) (u, 21) (v, 22) (w, 23) (x, 24) (y, 25) (z, 26) 

ถ้าเรารู้จักฟังก์ชั่น ord() [https://docs.python.org/3/library/functions.html#ord] เราจะสามารถเขียนฟังก์ชั่นแบบ char2num ได้สั้นขึ้นดังนี้:

In [7]:
def char2numShort(c):
    """
    เปลี่ยนตัวอักษร c เป็นตัวเลข เช่น a -> 1, b -> 2, ..., z->26
    ถ้าตัวอักษร c เป็นตัวอักษรตัวใหญ่ (A, B, C,...) ให้เปลี่ยนเป็นตัวเล็กก่อนแล้วค่อยเปลี่ยนเป็นตัวเลข
    ถ้าตัวอักษร c ไม่อยู่ใน a-z ให้ตัวเลขเป็น 0
    """    
    lc = c.lower() #เปลี่ยนอักษรเป็นอักษรตัวเล็กก่อน A->a, B->b, ...
    if lc in "abcdefghijklmnopqrstuvwxyz":
        return(ord(lc)-96)  #ord('a') = 97, ord('b') = 98, ... 
    else:
        return(0)
In [8]:
#ทดลองหาค่าของ a, b, x, z, % ควรได้ค่าเป็น 1, 2, 24, 26, 0
print(char2numShort('a'))
print(char2numShort('b'))
print(char2numShort('x'))
print(char2numShort('z'))
print(char2numShort('%'))
1
2
24
26
0

เมื่อเรามีฟังก์ชั่นแบบ char2num หรือ char2numShort แล้ว เราก็สามารถหาค่าตัวเลขของคำต่างๆได้ดังนี้:

In [9]:
sum = 0
for i in "attitude":  #i จะมีค่าเป็น 'a', 't', 't', 'i', 't', 'u', 'd', 'e'
    sum = sum + char2num(i)
print(sum) #ควรออกมาเป็น 100
100

เนื่องจากเราต้องหาค่าตัวเลขของคำจำนวนมาก เราควรสร้างฟังก์ชั่นไว้ใช้กับคำเหล่านั้นดังนี้:

In [10]:
def word2num(word):
    "เปลี่ยนคำเป็นผลรวมของตัวเลขของตัวอักษรแต่ละตัว a -> 1, b -> 2, ..., z->26"
    sum = 0
    for i in word:
        sum = sum + char2num(i)
    return(sum)
In [11]:
#ทดลองใช้ word2num
print(word2num('attitude')) #100
print(word2num('HardWork')) #98
print(word2num('hard work')) #98
print(word2num('KNOWLEDGE')) #96
print(word2num('m-o-n-e-y')) #72
print(word2num("123[]%$-_\n")) #0
100
98
98
96
72
0

เมื่อมีฟังก์ชั่นอย่าง word2num แล้ว เราก็แค่เปิดไฟล์ที่มีคำภาษาอังกฤษ 1 คำต่อบรรทัดแล้วก็คำนวณค่าตัวเลขของคำ ถ้าคำไหนมีค่าเท่ากับ 100 เราก็เขียนเก็บลงไฟล์แบบนี้:

In [12]:
wordlist = '/usr/share/dict/words' #ไฟล์ที่มีคำภาษาอังกฤษ 1 คำต่อบรรทัด
word100  = 'word100.txt' #เราเก็บผลลัพธ์เราไว้ในไฟล์นี้
inputfile = open(wordlist) #เปิดไฟล์เพื่ออ่าน
outputfile = open(word100, "w") #เปิดไฟล์เพื่อเขียน สังเกตว่ามี "w"
for word in inputfile: 
    #เราไม่ต้อง word = word.strip() 
    #เพราะเราเขียน word2num ให้ไม่สนใจตัวอักษรที่ไม่ใช่ a-z, A-Z 
    #ดังนั้นสามารถเก็บ \n ไว้ตอน outputfile.write(...)เลย
    if word2num(word) == 100:
        outputfile.write(word) 
outputfile.close()
inputfile.close()

พบว่าไฟล์ word100.txt มีคำกว่า 2,000 คำ ยกตัวอย่างเช่นคำเหล่านี้ (ใช้เทคนิคที่ยังไม่ได้สอนเด็กดังนี้: อ่านทุกบรรทัดในไฟล์ด้วย readlines, สุ่มเลือกคำมาด้วย random.sample, และสร้าง list ด้วย list comprehension [https://www.programiz.com/python-programming/list-comprehension]):

In [13]:
import random
[x[:-1] for x in random.sample(open('word100.txt').readlines(), 20)]
Out[13]:
['beguileful',
 'farriery',
 'sensoria',
 'mercantile',
 'clausure',
 'washway',
 'rumpadder',
 'shipplane',
 'pyralis',
 'Murillo',
 'mirrored',
 'avocation',
 'nodality',
 'Sapindales',
 'knothole',
 'pluries',
 'ascophore',
 'censorate',
 'Celticist',
 'retiring']
In [ ]: