วิธีคิดแบบนักวิทยาการคอมพิวเตอร์/Strings
บทที่ 7 Strings
แก้ไข7.1 A compound data type
แก้ไขจนถึงตอนนี้เราได้เห็น 3 รูปแบบ: int, float, และ string string มีคุณภาพแตกกต่างจากตัวอื่นๆที่กล่าวมา เนื่องจาก มันสร้างขึ้นด้วยตัวอักษรหลายตัวรวมกัน
รูปแบบชนิดที่ประกอบด้วยชิ้นส่วนเล็กๆเรียกว่า compound data types ขึ้นอยู่กับว่าเรากำลังอะไร เราอาจต้องการที่จะทำ compound data types เป็นสิ่งเดียว หรือเราอาจต้องการที่จะเข้าไปในส่วนของมัน ความคลุมเครือนี้มีประโยชน์
สัญลักษณ์ bracket เลือกตัวอักษรตัวเดียวจาก string.
>>> fruit = “banana”
>>> letter = fruit
>>> print letter
expression fruit[1] เลือกตัวอักษรที่เป็นตัวแรกจาก fruit. ตัวแปรที่เป็นอักษรอ้างถึงผลลัพธ์. เมื่อเราแสดงตัวอักษร เราได้รับความประหลาดใจ:
a
ตัวอักษรตัวแรกของ “banana” ไม่ใช่ a เว้นแต่คุณคือนักวิทยาศาสตร์คอมพิวเตอร์ ในกรณีนั้นคุณควรคิดถึง expression ในวงเล็บเป็นการเริ่มต้นจากการเริ่มต้นของ string และการเริ่มต้นของอักษรตัวแรกก็คือ 0 ดังนั้น b คือ อักษรลำดับ 0 (0th) ของ “banana”, a เป็นอักษรอันดับแรก และ n เป็นอักษรลำดับที่สอง
เพื่อที่จะได้ตัวอักษรตัวแรกของ string คุณต้องใส่ 0 หรือ expression ใดๆด้วยค่า 0 ในเครื่องหมายวงเล็บ:
>>> letter = fruit[0]
>>> print letter
b
expression ในเครื่องหมายวงเล็บเรียกว่า index index กำหนดสมาชิกของเซทคำสั่ง ในกรณีนี้เซทของตัวอักษรใน string index ชี้ให้เห็นสิ่งไหนที่คุณต้องการ ดังเช่นชื่อ มันสามารถเป็นได้ทั้ง integer expression ใดๆ
7.2 Length
แก้ไขlen ฟังก์ชั่น return ตัวเลขของตัวอักษรเป็น string:
>>>fruit = “banana”
>>>len(fruit)
6
เพื่อที่จะเอาตัวอักษรตัวสุดท้ายของ string คุณอาจจะต้องพยายามลองบางอย่างเช่นนี้:
length = len(fruit)
last = fruit[length] # ERROR!
มันไม่สามารถทำได้ มันทำให้เกิด runtime error IndexError: string index out of range เหตุผลคือมันไม่มีตัวอักษรลำดับที่หกใน “banana” ตั้งแต่เราได้เริ่มนับตั้งแต่ศูนย์ อักษรตัวที่หก ซึ่งมีหมายเลข 0 ถึง 5 เพื่อจะเอาตัวอักษรตัวสุดท้าย เราต้องทำการลบ 1 จาก length:
length = len(fruit)
last = fruit[length-1]
ตัวเลือก เราสามารถใช้ index ที่มีเครี่องหมายลบ(-) ซึ่ง นำย้อนหลังจากตัวสุดท้ายของ string expression fruit[-1] ให้ผลเป็นตัวอักษรตัวสุดท้าย fruit[-2] ให้ผลเป็นตัวอักษรตัวที่สองจากตัวสุดท้าย เป็นต้น
7.3 Travarsal and the for loop
แก้ไขการคำนวณที่มากมายรวมทั้งการดำเนินการ string หนึ่งตัวอักษรในแต่ละครั้งหนึ่ง บ่อยครั้งที่การคำนวณเริ่มที่ตัวแรกโดยเลือกตัวอักษรแต่ละตัวในครั้งนั้น ทำบางอย่างต่อมัน และทำต่อไปจนจบ รูปแบบของการดำเนินการเช่นนี้เรียกว่า traversal ทางเดียวที่จะ encode คือ ด้วย while statement:
index = 0
while index < len(fruit):
letter = fruit[index]
print letter
index = index + 1
loop นี้ traverse string และแสดงค่าแต่ละตัวอักษรบนบรรทัด. เงื่อนไขของ loop นี้คือ index < len(fruit) ดังนั้นเมื่อ index เท่ากับความยาวของ string เงื่อนไขจะเป็น false และ body ของ loop จะไม่ถูกดำเนินการ การเข้าถึงตัวอักษรตัวสุดท้ายคือด้วย index len(fruit)-1 ซึ่งคือตัวอักษรตัวสุดท้ายใน string
การใช้ index ในการ traverse กลุ่มของค่านั้นธรรมดามากซึ่ง Python ได้จัดสรรทางเลือกเอาไว้ syntax ง่ายๆ – for loop:
for char in fruit:
print char
ในแต่ละครั้งที่ที่เข้าไปใน loop ตัวอักษรตัวถัดไปจะถูกกำหนดค่าให้กับตัวแปร char loopจะดำเนินต่อไปจนไม่มีตัวอักษรเหลืออยู่
ตัวอย่างต่อไปนี้แสดงถึง การเชื่อมต่ออละ for loop ในการสร้าง abecedarian series “Abecedarian” อ้างถึงลำดับหรือรายการ ซึ่ง element ปรากฏใน คำสั่งเรียงตัวอักษร. ตัวอย่าง ในหนังสือของ Robert McCloskey Make Way for Ducklings, ชื่อของ ducklings คือ Jack, Kack, Lack, Mack, Nack, Ouack, Pack, และ Quack. loop นี้แสดงชื่อเหล่านี้ในคำสั่ง:
prefixes = “JKLMNOPQ”
suffix = “ack”
for letter in prefixes:
print letter + suffix
ผลลัพธ์ของโปรแกรมนี้คือ:
Jack
Kack
Lack
Mack
Nack
Oack
Pack
Qack
แน่นอน ยังไม่ค่อยถูกต้องมากนัก เนื่องจาก “Ouack” และ “Quack” ไม่ได้มีการสะกด
7.4 String slices
แก้ไขกลุ่มของ string ถูกเรียกว่า slice การเลือก slice คล้ายกันกับการเลือกตัวอักษร:
>>> s = “Peter, Paul, and Mary”
>>> print s[0:5]
Peter
>>> print s[7:11]
Paul
>>> print s[17:21]
Mary
operator [n:m] return ส่วนของ string จากตัวอักษรตำแหน่งที่ n ถึงตำแหน่งที่ m รวมถึงตัวอักษรตัวแรกแต่ไม่รวมตัวอักษรตัวสุดท้าย มันจะทำให้เข้าใจมากขึ้นถ้าคุณนึกถึง การชี้ตำแหน่งของ indices ระหว่างตัวอักษร ดังใน diagram ต่อไปนี้
ถ้าคุณละเลย index(ตัวแปรหรือค่าซึ่งใช้เลือกสมาชิกของเซท เช่นตัวอักษรจาก string) ตัวแรก ก่อนเครื่องหมาย colon ส่วนที่หั่นออกจะเริ่มตั้งแต่ต้นของstring ถ้าหากละเลย index ตัวที่สอง ส่วนที่หั่นออกจะไปยังท้ายของ string
ดังนี้:
>>> fruit = “banana”
>>> fruit [:3]
‘ban’
>>> fruit [3:]
‘ana’
คุณคิดว่า s[:] หมายถึงอะไร?
7.5 String comparison
แก้ไขoperator ที่ใช้ในการเปรียบเทียบ ทำงานกับ strings มาดูว่าหาก string สองตัวเท่ากัน:
if word == “banana”:
print “Yes, we have no bananas!”
operator ในการเปรียบเทียบตัวอื่นๆมีประโยชน์สำหรับคำสั่งการวางคำที่เรียงตามตัวอักษร:
if word < “banana”:
print “your word, ” + word + “, comes before banana.”
elif word > “banana”:
print “your word, ” + word + “, comes after banana.”
else:
print “Yes, we have no bananas!”
คุณควรระวัง อย่างไรก็ตาม Python ไม่สามารถดูแลตัวอักษรพิมท์ใหญ่และพิม์เล็กเช่นเดียวกับที่มนุษย์ทำ ตัวอักษรพิมพ์ใหญ่ทั้งหมดมาก่อนตัวอักษรพิมพ์เล็ก ดังผลลัพธ์
Your word, Zebra, comes before banana.
วิธีที่จะจัดการกับปัญหานี้คือเปลี่ยน string ไปเป็นรูปแบบมาตรฐาน เช่น ตัวอักษรพิมพ์เล็กทั้งหมด ก่อนที่จะกระทำการเปรียบเทียบ. ปัญหาที่ยุ่งยากมากกว่านี้ก็คือ การทำให้โปรแกรมเข้าใจว่า zebra ไม่ได้เป็น fruit
7.6 String are immutable
แก้ไขการทดสอบการใช้ operator [] ที่ข้างซ้ายของการกำหนดค่า, ด้วยความตั้งใจที่จะเปลี่ยนตัวอักษรใน string. ตัวอย่าง:
greeting = “Hello, world!”
greeting[0] = ‘J’ # ERROR!
print greeting
แทนที่จะสร้างผลลัพธ์ Jello, world! code นี้ทำให้เกิด runtime error TypeError: object doesn’t support item assignment
string ไม่มีการเปลี่ยนแปลง ซึ่งหมายถึงคุณไม่สามารถที่จะเปลี่ยน string ที่มีอยู่ได้ ดีที่สุดที่คุณสามารถทำได้คือ สร้าง string ใหม่ขึ้นมาซึ่งมีการเปลี่ยนแปลงบน original ของมัน:
greeting = “Hello, world!”
newGreeting = ‘J’ + greeting[1:]
print newGreeting
วิธีแก้ปัญหานี้คือ การเชื่อมต่อตัวอักษรตัวแรกที่เป็นตัวใหม่ไปยัง slice ของ greeting การกระทำนี้ไม่มีผลกระทบต่อ original string
7.7 A find function
แก้ไขfunction ต่อไปนี้ทำอะไร?
def find(str, ch):
index = 0
while index < len(str):
if str[index] == ch:
return index
index = index + 1
return -1
ในความเข้าใจ find ตรงกันข้ามกันกับ [] operator. แทนที่จะเอา index และตัดทอนตัวอักษรที่คล้ายกัน มันเลือกตัวอักษรและหา index ที่ตัวอักษรนั้นปรากฏอยู่ ถ้าไม่เจอตัวอักษร function return -1
นี่เป็นตัวอย่างแรกที่เราได้เห็น return statement อยู่ใน loop ถ้า str[index] == ch, function return ในทันที, ออกจาก loop ก่อนกำหนด
ถ้าตัวอักษรไม่ได้ปรากฏใน string จากนั้นโปรแกรมก็จะออกจาก loop และ return -1.
7.8 Looping and counting
แก้ไขโปรแกรมต่อไปนี้นับเลขในแต่ละครั้งที่ตัวอักษรปรากฏใน string:
fruit = “banana”
count = 0
for char in fruit:
if char == ‘a’:
count = count + 1
print count
โปรแกรมนี้สาธิตรูปแบบอื่นๆของการคำนวณที่เรียกว่า counter ตั้วแปร count ในเริ่มแรกคือ 0 และหลังจากนั้นจะเพิ่มขึ้นในแต่ละครั้งที่เจอตัวอักษร a. เมื่อออกจาก loop count จะมีผลลัพธ์เป็นผลรวมของตัวอักษร a
7.9 The string module
แก้ไขString module ประกอบด้วย function ที่เป็นประโยชน์ที่ช่วยจัดการกับ string โดยปรกติ เราต้องทำการ import module ก่อนที่เราจะทำการใช้งานมัน:
>>> import string
String module ประกอบด้วย function ที่มีชื่อว่า find ที่ทำงานอย่างเดียวกับ function ที่เราเคยเขียนไว้. การเรียกมันเราต้องกำหนดชื่อของ module และชื่อของ function โดยใช้เครื่องหมาย dot (.)
>>> fruit = “banana”
>>> index = string.find(fruit, “a”)
>>> print index
1
ตัวอย่างนี้สาธิตหนึ่งในข้อได้เปรียบของ module – ซึ่งช่วยหลีกเลี่ยงการขัดแย้งกันระหว่างชื่อของ function ที่สร้างขึ้นภายใน และ function ที่ผู้ใช้งานกำหนดขึ้น ด้วยการใช้เครื่องหมาย dot (.) เราสามารถกำหนดเวอร์ชั่นของ find ที่เราต้องการได้
อันที่จริง string.find มีความเป็นทั่วไปมากกว่าเวอร์ชั่นที่เราได้เขียนไว้ อย่างแรก มันสามารถหา substrings ไม่ได้หาแค่เพียงตัวอักษร:
>>> string.find(“banana”, “na”)
2
เช่นเดียวกัน มันสามารถเอา argument มาเพิ่มเพื่อกำหนดว่า index ควรเริ่มจากตำแหน่งไหน:
>>> string.find(“banana”, “na”, 3)
4
หรือเพิ่ม argument 2ตัว เพื่อกำหนดระยะของ indices:
>>> string.find(“bob”, “b”, 1, 2)
-1
ในตัวอย่างนี้ การค้นหาล้มเหลวเนื่องจากตัวอักษร b ไม่ได้ปรากฏใน index ในระยะจาก 1 ถึง 2 (ไม่รวมถึง 2)
7.10 Character classification
แก้ไขมันสามาถใช้เป็นประโยชน์บ่อยครั้งเพื่อตรวจสอบตัวอักษรและทดสอบไม่ว่ามันจะเป็นตัวอักษรพิมพ์เล็กหรือตัวอักษรพิมพ์ใหญ่ หรือไม่ว่ามันจะเป็นตัวอักษรหรือตัวเลข String module จัดสรร constant หลายๆอย่างซึ่งมีประโยชน์ต่อวัตถุประสงค์นี้
String string.lowercase ประกอบด้วย ตัวอักษรทั้งหมดซึ่งระบบพิจารณาแล้วว่าเป็นตัวอักษรพิมพ์เล็กเช่นเดียวกับ string.uppercase ประกอบด้วย ตัวอักษรพิมพ์ใหญ่ทั้งหมด ลองต่อไปนี้และดูว่าคุณได้อะไรบ้าง:
>>> print string.lowercase
>>> print string.uppercase
>>> print string.digits
เราสามารถใช้ constant เหล่านี้และ find แบ่งประเภทของตัวอักษร. ตัวอย่าง, ถ้า find(lowercase, ch) return ค่าที่นอกเหนือจาก -1 ดังนั้น ch ต้องเป็นตัวอักษรพิมพ์เล็ก:
def isLower(ch):
return string.find(string.lowercase, ch) != -1
ตัวเลือก เราสามารถนำข้อได้เปรียบของ in operator ซึ่งได้กำหนดตัวอักษรที่ปรากฏใน string:
def isLower(ch):
return ch in string.lowercase
ยังไม่มีตัวเลือกตัวอื่น เราสามารถใช้ operator ที่ใช้ในการเปรียบเทียบ:
def isLower(ch):
return ‘a’ <= ch <= ‘z’
ถ้า ch อยู่ระหว่าง a และ z มันจะต้องเป็นตัวอักษรพิมพ์เล็ก.
Constant ตัวอื่นๆที่ถูกกำหนดใน string module อาจทำให้คุณประหลาดใจเมื่อคุณ print มัน:
>>> print string.whitespace
Whitespace เปลี่ยนตำแหน่ง cursor โดยไม่ทำการ print ค่าใดๆ มันจะสร้าง white space ระหว่างตัวอักษรที่มองไม่เห็น Constant string whitespace ประกอบด้วย ตัวอักษร whitespace ทั้งหมด รวมถึง space, tab (\t), และขึ้นบรรทัดใหม่ (\n)
7.11 Glossary
แก้ไขcompound data type: A data type in which the values are made up of components, or elements, that are themselves values.
traverse: To iterate through the elements of a set, performing a similar operation on each.
index: A variable or value used to select a member of an ordered set, such as a character from a string.
slice: A part of a string specified by a range of indices.
mutable: A compound data types whose elements can be assigned new values.
counter: A variable used to count something, usually initialized to zero and then incremented.
increment: To increase the value of a variable by one.
decrement: To decrease the value of a variable by one.
whitespace: Any of the characters that move the cursor without printing visible characters. The constant string.whitespace contains all the whitespace characters.