วิธีคิดแบบนักวิทยาการคอมพิวเตอร์/Lists

จาก วิกิตำรา
ไปยังการนำทาง ไปยังการค้นหา

บทที่ 8 Lists[แก้ไข]

List คือ ชุดของค่า ที่ซึ่งแต่ละค่าถูกค้นพบด้วย index ค่าที่ถูกสร้างขึ้นเป็น list จะเรียกว่า elements

List คล้ายกันกับ strings ซึ่งเป็นชุดของตัวอักษร นอกจากนี้ elements ของ list นั้น สามารถมี typeได้ทุกแบบ Lists และ strings – และสิ่งที่นอกจากนี้ที่ทำตัวเหมือนกันกับ ชุดของการจัดเรียง – เรียกว่า sequences

8.1 List values[แก้ไข]

มีหลากหลายทางที่จะสร้าง list ขึ้นมาใหม่; ที่ง่ายที่สุดคือ ล้อมค่า elements ในวงเล็บสี่เหลี่ยม ([ and ]):

[10, 20, 30, 40]

[“spam”, “bungee”, “swallow”]

ตัวอย่างแรกคือ list ของ integers(ข้อมูลชนิดตัวเลขจำนวนเต็ม)สี่ตัว ตัวอย่างที่สองคือ list ของ strings (ข้อมูลชนิดข้อความ) Elements ของ list ไม่จำเป็นต้องมี type แบบเดียวกัน List ต่อไปนี้ประกอบด้วย string, float, integer, และ list อีกตัวหนึ่ง:

[“hello”, 2.0, 5, [10, 20]]

List ที่อยู่ภายใน list จะถูกกล่าวว่าเป็น nested

List ที่ประกอบด้วย จำนวนเต็มที่ต่อเนื่องตามลำดับนั้นธรรมดา Python ให้วิธีการง่ายๆในการสร้างมัน:

>>> rang (1,5)

[1, 2, 3, 4]

Function range มีสอง argument และ return list ที่ประกอบด้วยตัวเลขจำนวนเต็มทั้งหมดจาก argument ตัวแรกถึงตัวสุดท้าย รวมตัวแรกแต่ไม่รวมถึงตัวเลขที่เป็น argument ตัวที่สอง!

มีอีกสองรูปแบบของ range ด้วย argument เพียงตัวเดียว มันสร้าง list ที่เริ่มต้นจาก 0:

>>> range(10)

[1, 2, 3, 4, 5, 6, 7, 8, 9]

ถ้ามี argument ตัวที่สาม มันกำหนดช่องว่างระหว่างค่าที่ต่อเนื่องกัน, ซึ่งเรียกว่า step size ตัวอย่างนี้นับจาก 1 ถึง 10 ด้วยระยะก้าวคือ 2:

>>> rang(1,10,2)

[1, 3, 5, 7, 9]

โดยสรุป มี list พิเศษที่ไม่ได้ประกอบด้วย element มันถูกเรียกว่า empty list และมันหมายถึง []

ด้วยวิธีการเหล่านี้ในการสร้าง list มันจะน่าผิดหวัง ถ้าเราไม่สามารถกำหนดค่า list เป็นตัวแปรหรือส่ง list เป็น parameter สู่ functions. เราสามารถทำได้

vocabulary = [“ameliorate”, “castigate”, “defenstrate”]

numbers = [17, 123]

empty = []

print vocabulary, numbers, empty

[“ameliorate”, “castigate”, “defenstrate”] [17, 123] []

8.2 Accessing elements[แก้ไข]

Syntax สำหรับการเข้าถึง elements ของ list คือ syntax เดียวกันกับการเข้าถึง characters(ข้อมูลชนิดอักขระ) ของ string – สัญลักษณ์วงเล็บ ([]) expression ภายในวงเล็บกำหนด index จำไว้ว่า indices เริ่มต้นจาก 0:

print number[0]

numbers[1] = 5

สัญลักษณ์วงเล็บ สามารถปรากฏได้ทุกที่ใน expression เมื่อมันปรากฏขึ้นในทางข้างซ้ายของการกำหนดค่ามันเปลี่ยนแปลงหนึ่งใน element ของ list นั้น ดังนั้น element ตัวที่ 1-eth ซึ่งเคยเป็น 123 ตอนนี้คือ 5

integer expression ใดๆ สามารถใช้เป็น index ได้:

>>> number[3-2]

5

>>> number[1.0]

TypeError: sequence index must be integer

ถ้าคุณลองอ่านหรือลองเขียน element ซึ่งไม่ได้มีอยู่ คุณก็จะได้ runtime error:

>>> numbers[2] = 5

IndexError: list assignment index out of range

ถ้า index เป็นค่าลบ มันจะนับถอยหลังจากตัวสุดท้ายของ list:

>>> numbers[-1]

5

>>> numbers[-2]

17

>>> numbers[-3]

IndexError: list index out of range

numbers[-1] คือ element ตัวสุดท้ายของ list numbers[-2] คือ element ตัวสองตัวก่อนสุดท้ายของ list, และ numbers[-3] ไม่ได้มีอยู่

มันธรรมดาที่ใช้ตัวแปร loop เป็น list index

horsemen = [“war”, “famine”, “pestilence”, “death”]

i = 0

while i < 4:

print horsemen[i]

i = i + 1

loopนี้นับจาก 0 ถึง 4 เมื่อตัวแปร loop i คือ 4 เงื่อนไขผิดพลาดและ loop สิ้นสุด ดังนั้น body ของ loop จะทำการดำเนินการเพียงเมื่อ i คือ 0, 1, 2, และ 3

แต่ละครั้งที่เข้าไปใน loop ตัวแปร i ถูกใช้เป็น index เข้าไปใน list ทำการ print i-eth element รูปแบบการคำนวณแบบนี้เรียกว่า list traversal

8.3 List length[แก้ไข]

function len จะ return ค่าความยาวของ list. มันเป็นความคิดที่ดีที่จะใช้ค่านี้แทนค่าคงที่ วิธีนั้น ถ้าขนาดของ list เปลี่ยนไป คุณไม่ต้องตรวจสอบโปรแกรมโดยการเปลี่ยน loop ทั้งหมด; มันจะทำงานอย่างถูกต้องสำหรับ list ทุกๆขนาด:

horsemen = [“war”, “famine”, “pestilence”, “death”]

while i < len(horsemen):

print horsemen[i]

i = i + 1

ในครั้งสุดท้ายของ loop ที่ถูกดำเนินการ i คือ len(horsemen) – 1 ซึ่งเป็น index ของ element ตัวสุดท้าย. เมื่อ i เท่ากับ len(horsemen) เงื่อนไขจะล้มเหลวและ body จะไม่ถูกดำเนินการ ซึ่งเป็นสิ่งที่ดี เนื่องจาก len(hoesemen) ไม่ได้เป็น index ที่ถูกต้อง

ถึงแม้ว่า list สามารถประกอบไปด้วย list อื่นๆ list ที่อยู่ภายในยังคงนับว่าเป็น element ตัวหนึ่งๆ ความยาวของ list นี้คือ 4:

[‘spam!’, 1, [‘Brie’, ‘Roquefort’, ‘Pol le Veq’], [1, 2, 3]]

8.4 List membership[แก้ไข]

in เป็น boolean operator ซึ่งตรวจสอบสมาชิกในลำดับ. เราเคยใช้มันใน หมวด 7.10 กับ strings แต่มันทำงานเช่นเดียวกันกับ list และ sequence อื่นๆ:

>>> horsemen = [“war”, “famine”, “pestilence”, “death”]

>>> ‘pestilence’ in horsemen

True

>>> ‘debauchery’ in horsemen

False

“pestilence” เป็นสมาชิกของ horsemen list, in operator จะ return ค่า true. “debauchery” ไม่ได้อยู่ใน list, in return ค่า false

เราสามารถใช้ not รวมกันกับ in เพื่อตรวจสอบว่า element ไหนที่ไม่ได้เป็นสมาชิกของ list:

>>> ‘debauchery’ not in horsemen

True

8.5 List and for loops[แก้ไข]

for loop ที่เราเห็นกันไปในหมวดที่ 7.3 ทำงานร่วมกับ lists ได้เช่นเดียวกัน. โดยทั่วๆปิ syntax ของ for loop คือ:

for VARIABLE in LIST:

BODY

Statement นี้จะมีค่าเท่ากันกับ:

i = 0

while i < len(LIST):

VARIABLE = LIST[i]

BODY

i = i + 1

for loop จะสั้นและได้ใจความมากกว่าเนื่องจากเราสามารถตัดตัวแปร loop ออกไปได้ i.

นี่คือ loop ที่ได้กล่าวมาข้างต้น ซึ่งเขียนด้วย for loop

for horseman in horsemen:

print horseman

มันแทบจะอ่านเหมือนในภาษาอังกฤษ:

“For (every) horseman in (the list of) horsemen, print (the name of the) horseman”

list expression ใดๆก็สามารถใช้ใน for loop ได้:

for number in range(20):

if number % 2 == 0:

print number

for fruit in [“banana”, “apple”, “quince”]:

print “I like to eat” + fruit + “s!”

ตัวอย่างแรก แสดงเลขคู่ทั้งหมดระหว่าง 0 และ 19 ตัวอย่างที่สองแสดงเป็นคำพูดแสดงความสนใจสำหรับผลไม้หลากหลายชนิด

8.6 List operations[แก้ไข]

สัญลักษณ์ + ใช้เชื่อมต่อ lists เข้าด้วยกัน:

>>> a = [1, 2, 3]

>>> b = [4, 5, 6]

>>> c = a + b

>>> print c

[1, 2, 3, 4, 5, 6]

ในทำนองเดียวกัน สัญลักษณ์ * กระทำซ้ำ list:

>>> [0] * 4

[0, 0, 0, 0]

>>> [1, 2, 3] * 3

[1, 2, 3, 1, 2, 3, 1, 2, 3]

ตัวอย่างแรกกระทำซ้ำกับ [0] 4ครั้ง ตัวอย่างที่สอง กระทำซ้ำกับ [1, 2, 3] 3ครั้ง

8.7 List slices[แก้ไข]

การ slice ที่เราได้เห็นในหมวดที่ 7.4 ทำงานร่วมกับ list ได้เช่นเดียวกัน:

>>> list = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’]

>>> list [1:3]

[‘b’, ‘c’]

>>> list [:4]

[‘a’, ‘b’, ‘c’, ‘d’]

>>> list[3:]

[‘d’, ‘e’, ‘f’]

ถ้าคุณเว้น index ตัวแรก slice จะเริ่มต้นตั้งแต่แรก ถ้าคุณเว้น index ตัวที่สอง slice จะไปยังท้ายสุด ดังนั้นถ้าคุณเว้นว่างไว้ทั้งสองตัว slice จะทำการคัดลอก list ทั้งหมด

>>> list[:]

[‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’]

8.8 List are mutable[แก้ไข]

ไม่เหมือนกับ strings lists เปลี่ยนแปลงได้ ซึ่งหมายถึงเราสามารถเปลี่ยน elements ของมันได้ โดยใช้สัญลักษณ์วงเล็บ ทางด้านซ้ายของกี่กำหนดค่า เราสามารถอัพเดทหนึ่งใน elements:

>>> fruit = [“banana”, “apple”, “quince”]

>>> fruit [0] = “pear”

>>> fruit [-1] = “orange”

>>> print fruit

[“pear”, “apple”, “orange”]

ด้วย slice operator เราสามารถอัพเดท element หลายๆตัวในครั้งเดียว:

>>> list = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’]

>>> list[1:3] = [‘x’, ‘y’]

>>> print list

[‘a’, ‘x’, ‘y’, ‘d’, ‘e’, ‘f’]

เราสามารถลบ elements ออกจาก list ด้วยการกำหนดค่าว่างเปล่าให้กับมัน:

>>> list = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’]

>>> list[1:3] = []

>>> print list

[‘a’, ‘d’, ‘e’, ‘f’]

และเราสามารถเพิ่ม elements เข้าใน list ด้วยการบีบมันเข้าไปใน slice ที่ว่างเปล่าเข้าไปยังตำแหน่งที่ต้องการ:

>>> list = [‘a’, ‘d’, ‘f’]

>>> list[1:1] = [‘b’, ‘c’]

>>> print list

[‘a’, ‘b’, ‘c’, ‘d’, ‘f’]

>>> list[4:4] = [‘e’]

>>> print list

[‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’]

8.9 List deletion[แก้ไข]

การใช้ slice เพื่อลบ list elements ทำได้ไม่สะดวกนัก และมีแนวโน้มที่จะ error Python ให้ทางเลือกที่ง่ายต่อการอ่านมาก

del ลบ element ออกจาก list:

>>> a = [‘one’, ‘two’, ‘three’]

>>> del a[1]

>>> a

[‘one’, ‘three’]

อย่างที่คุณคาดไว้, del กระทำการปฏิเสธ indices และทำให้เกิด runtime error ถ้า index อยู่นอกขอบเขต

คุณสามารถใช้ slice แทน index สำหรับ del:

>>> list = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’]

>>> del list [1:5]

>>> print list

[‘a’, ‘f’]

โดยปรกติ slices เลือกเอา elements ทั้งหมด แต่ไม่รวม index ตัวที่สอง

8.10 Objects and values[แก้ไข]

ถ้าเราดำเนินการ statements การกำหนดค่าให้กับตัวแปนเหล่านี้

a = “banana”

b = “banana”

เรารู้ว่า a และ b จะอ้างถึง string ด้วยตัวอักษร “banana” แต่เราไม่สามารถบอกได้ว่ามันจะชี้ string ตัวเดียวกันหรือไม่

สามารถเกิดขึ้นได้ทั้ง 2 สถานการณ์:

Ch8-1.jpg

ในกรณีแรก a และ b อ้างถึงทั้งสองสิ่งที่ต่างกันซึ่งมี่คาเดียวกัน ในกรณีที่สอง a และ b อ้างถึงสิ่งเดียวกัน สิ่งที่ถูกอ้างถึงนี้เรียกว่า objects, Object คือ สิ่งที่ตัวแปรสามารถอ้างถึง

ทุกๆ object มีตัวชี้ลักษณะเฉพาะ อันซึ่งเราสามารถด้วย id function โดยแสดงตัวชี้รายละเอียดของ a และ b เราสามารถบอกได้ว่าพวกมันอ้างถึง object ตัวเดียวกันหรือไม่

>>> id (a)

135044008

>>> id (b)

135044008

โดยแท้จริงแล้ว เราจะได้รับตัวชี้รายละเอียดเป็นตัวเดียวกันทั้งสอง ซึ่งหมายถึง Python สามารถสร้าง string ตัวเดียว และ a และ bทั้งคู่อ้างถึงมัน

>>> a = [1, 2, 3]

>>> b = [1, 2, 3]

>>> id (a)

135045528

>>> id (b)

135041704

ดังนั้นลักษณะ diagram จะดูเหมือนดังนี้:

Ch8-2.jpg

a และ b มีค่าเดียวกันแต่ไม่ได้อ้างถึง object ตัวเดียวกัน

8.11 Aliasing[แก้ไข]

เมื่อตัวแปรอ้างถึง objects, ถ้าเรากำหนดตัวแปรหนึ่งให้กับอีกตัวหนึ่ง, ตัวแปรทั้งสองตัวนั้นจะอ้างถึง object ตัวเดียวกัน:

>>> a = [1, 2, 3]

>>> b = a

ในกรณีนี้ diagram จะเหมือนดังนี้:

Ch8-3.jpg

เนื่องจาก list อันเดียวกันมีชื่อที่ต่างกันสองชื่อ a และ b เรากล่าวได้ว่ามันคือ aliased(ตัวแปรหลากหลายที่อ้างถึง object ตัวเดียวกัน)

การเปลี่ยนแปลง alias จะส่งผลถึงอีกตัวหนึ่ง:

>>> b[0] = 5

>>> print a

[5, 2, 3]

แม้ว่าการกระทำในลักษณะนี้จะมีประโยชน์ ในบางครั้งมันก้ไม่เป็นไปตามที่คาดหวังหรือไม่พึงปราถนา โดยทั่วไป มันจะปลอดภัยกว่าที่จะหลีกเลี่ยงการใช้ alias เมื่อคุณกำลังทำงานกับ object ที่เปลี่ยนแปลงง่าย อย่างนอน สำหรับ object ที่เปลี่ยนแปลงง่ายเหล่านี้ย่อมไม่มีปัญหา นั่นคือสาเหตุที่ว่าทำไม Python จึงเป็นอิสระต่อ alias strings เมื่อมันเป็นโอกาสที่จะทำให้ประหยัด

8.12 Cloning lists[แก้ไข]

ถ้าเราต้องการแก้ไข list และยังคงเก็บ copy จากต้นฉบับ เราจำเป็นต้องการความสามารถในการ copy ของ list มันเอง ไม่ใช่แค่การอ้างอิง. กระบวนการนี้บางครั้งเรียกว่า cloning เพื่อหลีกเลี่ยงความคลุมเคลือของคำว่า “copy”.

วิธีที่ง่ายที่สุดในการ clone list นั้นคือการใช้ slice operator:

>>> a = [1, 2, 3]

>>> b = a[:]

>>> print b

[1, 2, 3]

การนำ slice ใดๆของ list ใหม่สร้างขึ้น ในกรณีนี้ slice ที่เราได้สร้างขึ้นประกอบไปด้วยทั้งหมดของ list ที่เรา clone มา ตอนนี้เรามีอิสระในการเปลี่ยนแปลง b โดยไม่ต้องไปกังวลกับ a:

>>> b[0] = 5

>>> print a

[1, 2, 3]

8.13 List parameters[แก้ไข]

ผ่าน list เป็นอย่าง argument ปรกติผ่านตัวอ้างอิงไปยัง list ไม่ใช่การ copy ของ list. ตัวอย่าง function head เอา list เป็น parameter และ return element ตัวแรก:

def head(list):

return list[0]

นี่คือวิธีการใช้งาน:

>>> numbers = [1, 2, 3]

>>> head(numbers)

1

Parameter list และ ตัวแปร numbers เป็น alias สำหรับ object เดียวกัน

Diagram จะเหมือยเช่นนี้:

Ch8-4.jpg

เมื่อ list object ถูกใช้ร่วมโดยสองเฟรม เราจึงลากมาอยู่ระหว่างเฟรมทั้งสอง

ถ้า function แก้ไข list parameter ตัวเรียกเห็นการเปลี่ยนแปลง ตัวอย่าง deleteHead ลบ element ตัวแรกออกจาก list:

def deleteHead(list):

def list[0]

นี่คือวิธีการใช้งานของ deleteHead:

>>> numbers = [1, 2, 3]

>>> deleteHead(numbers)

>>> print numbers

[2, 3]

ถ้า function returns list มัน returns อ้างอิงไปยัง list ตัวอย่าง tail returns list ที่ประกอบด้วยทั้งหมด แต่ element ตัวแรกของ list ที่ได้ให้ไว้:

def tail(list):

return list[1:]

นี่คือวิธีการใช้งานของ tail:

>>> numbers = [1, 2, 3]

>>> rest = tail(numbers)

>>> print rest

[2, 3]

เนื่องจาก return ค่า ได้ถูกสร้างขึ้นด้วย slice operator มันเป็น list ใหม่. การสร้าง rest และ subsequence ใดๆเปลี่ยนไปเป็น rest จะไม่มีผลกับ numbers

8.14 Nested lists[แก้ไข]

Nested list เป็น list ที่ปรากฏเป็น element ในอีกlist หนึ่ง ใน list นี้ element ตัวลำดับที่สามเป็น nested list:

>>> list = [“hello”, 2.0, 5, [10, 20]]

ถ้าเรา print list[3], เราจะได้ [10, 20] เพื่อที่จะดึง element ออกมาจาก nested list เราสามารถทำได้ในสองขั้นตอน:

>>> elt = list[3]

>>> elt[0]

10

หรือเราสามารถผสมมัน:

>>> list [3][1]

20

เครื่องหมายวงเล็บประเมินผลจากซ้ายไปขวา ดังนั้น expression นี้ ได้ element ลำดับที่สามของ list และดึงเอา element ลำดับที่หนึ่งจากมันออกมา

8.15 Matrixes[แก้ไข]

Nested list บ่อยครั้งทำหน้าที่แทน matrices.ตัวอย่าง the matrix:

Ch8-5.jpg

อาจจะถูกแทนด้วยเช่นนี้:

>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

matrix เป็น list ด้วย สาม elements ที่แต่ละ element เป็นแถวของmatrix เราสามารถเลือกแถวทั้งหมดจาก matrix ด้วยวิธีปรกติ:

>>> matrix[1]

[4, 5, 6]

หรือเราสามารถตัดเอา element เพียงตัวเดียวจาก matrix โดยดารใช้รูปแบบ double-index:


>>> matrix[1][1]

5

index ตัวแรกเลือกแถว ตัวที่สองเลือกแถวในแนวตั้ง

8.16 String and lists[แก้ไข]

สอง functions ที่มีประโยชน์ใน string module เกี่ยวข้องกับ lists ของ strings Split function แยก string ไปเป็น list ของ คำ โดยอัตโนมัติ ตัวเลขใดๆของ ตัวอักษร whitespace ถูกพิจารณาขอบเขตของคำ:

>>> import string

>>> song = “The rain in Spain…”

>>> string.split(song)

[‘The’, ‘rain’, ‘in’, ‘Spain…’]

optional argument เรียกว่า delimiter สามารถใช้ระบุ character เพื่อใช้เป็นขอบเขตของคำ ตัวอย่างต่อไปนี้ใช้ string ai เป็น delimiter:

>>> string.split(song, ‘ai’)

[‘The r’, ‘n in Sp’, ‘n…’,]

ข้อสังเกต delimiter จำไม่ปรากฏใน list

Join function คือครงกันข้ามกันกับ split มันเอา list ของ string และเชื่อมต่อ elements ด้วย space ระหว่างแต่ละคู่:

>>> list = [‘The’, ‘rain’, ‘in’, ‘Spain…’]

>>> string.join(list)

‘The rain in Spain…’

เหมือน split, join เอา optional delimiter ใส่เข้าระหว่าง elements:

>>> string.join(list, ‘_’)

‘The_rain_in_Spain…’

8.17 Glossary[แก้ไข]

list: A named collection of objects, where each object is identified by an index.

index: An integer variable or value that indicates an element of a list.

element: One of the values in a list (or other sequence). The bracket operator selects elements of a list.

sequence: Any of the data types that consist of an ordered set of elements, with each element identified by an index.

nested list: A list that is an element of another list.

list traversal: The sequential accessing of each element in a list.

object: A thing to which a variable can refer.

aliases: Multiple variables that contain references to the same object.

clone: To create a new object that has the same value as an existing object. Copying a reference to an object creates an alias but doesn't clone the object.

delimiter: A character or string used to indicate where a string should be split.