5. โครงสร้างข้อมูล (Data Structure)
5.1 ลิสต์อีกที (More on Lists)
5.2 ประโยค del
(The del
statement)
5.3 ทูเปิล (Tuples and Sequences)
5.4 เซ็ต (Sets)
5.5 ดิกชันนารี (Dictionaries)
5.6 เทคนิกการวนรอบ (Looping Techniques)
5.7 เงื่อนไข (More on Conditions)
5.8 น้ำหนักของข้อมูลแบบลำดับ (Comparing Sequences and Other Types)
บทนี้จะอธิบายเทคนิกการใช้งานข้อมูล
5.1 ลิสต์อีกที (More on Lists)
เวลาใช้งานจริง เราจะใช้ลิสต์มากหน่อย เพราะมันเปลี่ยนแปลงค่าได้ เลยทำให้มีเมธอดของลิสต์เยอะหน่อย
append(x)
a[len(a):] = [x]
>>> a=[1,2,3] >>> a.append(4) >>> a [1, 2, 3, 4]
extend(L)
a[len(a):] = L
>>> a=[1,2,3] >>> L=[4,5,6] >>> a.extend(L) >>> a [1, 2, 3, 4, 5, 6]
insert(i, x)
a.insert(0, x)
ก็คือการไปแทรกข้างหน้าa.insert(len(a), x)
ก็คือการไปต่อท้าย คือa.append(x)
>>> a=[1,2,3] >>> a.insert(2,0) >>> a [1, 2, 0, 3]
remove(x)
>>> a=[1,2,3] >>> a.remove(2) >>> a [1, 3] >>> a.remove(2) Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: list.remove(x): x not in list
pop([i])
>>> a=[1,2,3] >>> a.pop(1) 2 >>> a [1, 3]
index(x)
>>> a=[1,2,3] >>> a.index(2) 1
count(x)
>>> a=[2,2,2,9,4,4,4,4] >>> a.count(2) 3
sort()
>>> a=[1,5,4,2,3] >>> a.sort() >>> a [1, 2, 3, 4, 5]
reverse()
>>> a=[1,5,4,2,3] >>> a.reverse() >>> a [3, 2, 4, 5, 1]
ตัวอย่างรวมอีกทีนึง
>>> a = [66.25, 333, 333, 1, 1234.5] >>> print a.count(333), a.count(66.25), a.count('x') 2 1 0 >>> a.insert(2, -1) >>> a.append(333) >>> a [66.25, 333, -1, 333, 1, 1234.5, 333] >>> a.index(333) 1 >>> a.remove(333) >>> a [66.25, -1, 333, 1, 1234.5, 333] >>> a.reverse() >>> a [333, 1234.5, 1, 333, -1, 66.25] >>> a.sort() >>> a [-1, 1, 66.25, 333, 333, 1234.5]
5.1.1 ทำลิสต์เป็นสแต็ค (Using Lists as Stacks)
ถ้าจะใช้งานลิสต์แบบสแต็คคือ เข้าก่อนออกหลัง ก็แค่ใช้เมธอดให้เหมาะสม คือเติมด้วย append()
แล้วเอาออกด้วย pop()
>>> stack = [3, 4, 5] >>> stack.append(6) >>> stack.append(7) >>> stack [3, 4, 5, 6, 7] >>> stack.pop() 7 >>> stack [3, 4, 5, 6] >>> stack.pop() 6 >>> stack.pop() 5 >>> stack [3, 4]
5.1.2 ใช้งานลิสต์แบบคิว (Using Lists as Queues)
คือ เข้าก่อนออกก่อน ก็ใช้ append()
และ pop(0)
ตามลำดับ
>>> queue = ["Eric", "John", "Michael"] >>> queue.append("Terry") # Terry arrives >>> queue.append("Graham") # Graham arrives >>> queue.pop(0) 'Eric' >>> queue.pop(0) 'John' >>> queue ['Michael', 'Terry', 'Graham']
5.1.3 ฟังก์ชั่นที่ใช้ในการโปรแกรมแบบฟังก์ชั่น (Functional Programming Tools)
มี 3 ตัว (ไม่นับคำสั่ง lambda
)
filter(function, sequence)
sequence
เฉพาะถ้า function
คืนค่าที่เป็นจริง (ไม่ใช่ศูนย์หรือ None
) งงนิดหน่อย ดูตัวอย่างดีกว่า เป็นการหาจำนวนเฉพาะ
>>> def f(x): return x % 2 != 0 and x % 3 != 0 ... >>> filter(f, range(2, 25)) [5, 7, 11, 13, 17, 19, 23]
map(function, sequence)
sequence
ไปทำงานใน function
แล้วคืนช่วงของผลลัพธ์ออกมาเป็นลิสต์
>>> def cube(x): return x*x*x ... >>> map(cube, range(1, 11)) [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
หาก function
ต้องการอาร์กิวเมนต์มากกว่าหนึ่งตัว ก็ต้องใส่ sequence
ด้วยจำนวนที่เท่ากัน
>>> seq = range(8) >>> def add(x, y): return x+y ... >>> map(add, seq, seq) [0, 2, 4, 6, 8, 10, 12, 14] >>> s2 = range(10,18) >>> map(add, seq, s2) [10, 12, 14, 16, 18, 20, 22, 24] >>> s3 = range(18, 10, -1) >>> map(add, seq, s3) [18, 18, 18, 18, 18, 18, 18, 18]
reduce(function, sequence)
sequence
ชุดแรก ไปเป็นข้อมูลนำเข้าให้ function
กับ sequence
ชุดต่อ ๆ ไป จนหมดข้อมูล
>>> def add(x,y): return x+y ... >>> reduce(add, range(1, 11)) 55
ถ้าไม่มีข้อมูลจาก sequence
จะแสดงข้อผิดพลาด
>>> reduce(add, range(0)) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: reduce() of empty sequence with no initial value
เพื่อเป็นการป้องการการผิดพลาดดังกล่าว อาจใส่อาร์กิวเมนต์ตัวที่สามซึ่งจะกลายเป็นค่าเริ่มต้นให้กับ function
เพื่อป้องกันกรณีลิสต์ว่าง ดังนี้
>>> def xsum(seq): ... def add(x,y): return x+y ... return reduce(add, seq, 0) ... >>> xsum(range(1, 11)) 55 >>> xsum([]) 0
5.1.4 ลิสต์จากลิสต์ (List Comprehensions)
เป็นโครงสร้างเฉพาะตัวของไพธอนที่ยืมมาจากภาษา Haskell/ML ในการสร้างลิสต์ใหม่จากลิสต์ที่มีอยู่ ใช้มากในไพธอน มีรูปแบบเป็น
[f(x) for x in L [ if p(x) ] ]
แปลว่า ให้สร้างลิสต์ด้วยฟังก์ชั่น f
จากลิสต์ L
สมาชิกต่อสมาชิก โดยแต่ละสมาชิกจะต้องมีค่า p(x)
ที่เป็นจริง
โครงสร้างส่วนหลัง ตรงที่เป็น if ...
เป็นตัวเลือก อาจใส่หรือไม่ก็ได้
ตัวอย่าง
>>> freshfruit = [' banana', ' loganberry ', 'passion fruit '] >>> [weapon.strip() for weapon in freshfruit] ['banana', 'loganberry', 'passion fruit'] >>> vec = [2, 4, 6] >>> [3*x for x in vec] [6, 12, 18] >>> [3*x for x in vec if x > 3] [12, 18] >>> [3*x for x in vec if x < 2] [] >>> [[x,x**2] for x in vec] [[2, 4], [4, 16], [6, 36]] >>> [x, x**2 for x in vec] # error - parens required for tuples File "<stdin>", line 1, in ? [x, x**2 for x in vec] ^ SyntaxError: invalid syntax >>> [(x, x**2) for x in vec] [(2, 4), (4, 16), (6, 36)] >>> vec1 = [2, 4, 6] >>> vec2 = [4, 3, -9] >>> [x*y for x in vec1 for y in vec2] [8, 6, -18, 16, 12, -36, 24, 18, -54] >>> [x+y for x in vec1 for y in vec2] [6, 5, -7, 8, 7, -5, 10, 9, -3] >>> [vec1[i]*vec2[i] for i in range(len(vec1))] [8, 12, -54] >>> [str(round(355/113.0, i)) for i in range(1,6)] ['3.1', '3.14', '3.142', '3.1416', '3.14159']
5.2 ประโยค del
(The del
statement)
ใช้งานคล้าย ๆ pop()
แต่เลือกช่วงได้ด้วย จึงต้องระบุดัชนีเสมอ
>>> a = [-1, 1, 66.25, 333, 333, 1234.5] >>> del a[0] >>> a [1, 66.25, 333, 333, 1234.5] >>> del a[2:4] >>> a [1, 66.25, 1234.5] >>> del a[:] >>> a []
สามารถใช้ del
ในการลบตัวแปรได้ด้วย
>>> del a
5.3 ทูเปิล (Tuples and Sequences)
ทูเปิลคล้ายกับลิสต์ ต่างกันตรงเป็นข้อมูลที่สามารถกำหนดค่าได้ครั้งเดียว จึงเหมาะที่จะใช้ในงานที่ต้องการค่าคงที่
ลิสต์ใช้วงเล็บก้ามปู []
แต่ทูเปิลใช้วงเล็บธรรมดา ()
หรืออาจละเลยไม่ใส่ก็ได้ โดยใส่แค่จุลภาค ,
ตามหลังสมาชิก (แต่ต้องระวังตัวเองงงเอง)
>>> t = 12345, 54321, 'hello!' >>> t[0] 12345 >>> t (12345, 54321, 'hello!') >>> # Tuples may be nested: ... u = t, (1, 2, 3, 4, 5) >>> u ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
ตัวอย่างการละเลยการใส่วงเล็บ ซึ่งถ้าดูผ่าน ๆ อาจสับสนได้
>>> empty = () >>> singleton = 'hello', # <-- note trailing comma >>> len(empty) 0 >>> len(singleton) # ได้ค่าเป็น 1 เพราะเป็นทูเปิลที่มีสมาชิก 1 ตัว 1 >>> singleton ('hello',)
การละเลยการใส่วงเล็บในตอนกำหนดค่า ไพธอนเรียกว่า การอัดข้อมูลเป็นอนุกรม (sequence packing) ในกรณีนี้คือ tuple packing (ถ้าละเลยการใส่วงเล็บแล้ว จะถือว่าเป็นข้อมูล tuple เสมอ)
t = x, y, z
และยังสามารถกำหนดค่าแบบย้อนกลับได้ อันนี้เรียกว่า การแตกข้อมูลอนุกรม (sequence unpacking)
x, y, z = t
(ซึ่งถ้าเขียนให้ถูกจริง ๆ แล้วคือ (x, y, z) = t
)
และแน่นอนว่าใช้กับลิสต์ได้เช่นเดียวกัน
[x, y, z] = t
5.4 เซ็ต (Sets)
ไพธอนรุ่นหลัง เติมความสามารถเรื่องเซ็ตเข้าไป ซึ่งเซ็ตก็คือลิสต์ที่สามารถใช้งานในลักษณะเซ็ตได้ เช่น การทำยูเนียนและอินเตอร์เซคเป็นต้น
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] >>> fruit = set(basket) # create a set without duplicates >>> fruit set(['orange', 'pear', 'apple', 'banana']) >>> 'orange' in fruit # fast membership testing True >>> 'crabgrass' in fruit False >>> # Demonstrate set operations on unique letters from two words ... >>> a = set('abracadabra') >>> b = set('alacazam') >>> a # unique letters in a set(['a', 'r', 'b', 'c', 'd']) >>> a - b # letters in a but not in b set(['r', 'd', 'b']) >>> a | b # letters in either a or b set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l']) >>> a & b # letters in both a and b set(['a', 'c']) >>> a ^ b # letters in a or b but not both set(['r', 'd', 'b', 'm', 'z', 'l'])
5.5 ดิกชันนารี (Dictionaries)
เป็นชนิดข้อมูลพิเศษที่อยู่ในรูป {key: value, ...}
- เปลี่ยนแปลงค่าได้
key
อาจเป็นข้อมูลชนิดสคริง ตัวเลข หรือทูเปิลที่ไม่ได้บรรจุ multable object ไว้- ลิสต์ใช้เป็นคีย์ไม่ได้ เพราะมันเปลี่ยนค่าภายในได้
- ลบค่าภายในได้ด้วยประโยค
del
- ถ้าใส่ค่าคีย์ซ้ำ จะแทนที่ค่าเก่า
- ถ้าค้นคีย์ที่ไม่มีอยู่ จะแสดงข้อผิดพลาด
- ใช้เมธอด
keys()
ในการแสดงค่าคีย์ทั้งหมด และใช้เมธอดhas_key()
ในการค้นค่าคีย์ - สมาชิกภายใน จะถูกเรียงลำดับด้วยค่าของคีย์โดยอัตโนมัติ
>>> tel = {'jack': 4098, 'sape': 4139} >>> tel['guido'] = 4127 >>> tel {'sape': 4139, 'guido': 4127, 'jack': 4098} >>> tel['jack'] 4098 >>> del tel['sape'] >>> tel['irv'] = 4127 >>> tel {'guido': 4127, 'irv': 4127, 'jack': 4098} >>> tel.keys() ['guido', 'irv', 'jack'] >>> tel.has_key('guido') True >>> 'guido' in tel True
แปลงทูเปิลในลิสต์มาเป็นดิกชันนารีด้วยฟังก์ชั่น dict()
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) {'sape': 4139, 'jack': 4098, 'guido': 4127} >>> dict([(x, x**2) for x in (2, 4, 6)]) # use a list comprehension {2: 4, 4: 16, 6: 36}
หรือหากค่าคีย์เป็นสตริงล้วน อาจกำหนดค่าแบบนี้ก็ได้ (เลียนแบบการส่งผ่านค่าไปยังฟังก์ชั่น)
>>> dict(sape=4139, guido=4127, jack=4098) {'sape': 4139, 'jack': 4098, 'guido': 4127}
5.6 เทคนิกการวนรอบ (Looping Techniques)
iteritems()
- ใช้แตกค่าคู่ของดิกชันนารี
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} >>> for k, v in knights.iteritems(): ... print k, v ... gallahad the pure robin the brave
enumerate()
- ใช้แปลงจากลิสต์ (หรือทูเปิล) มาเป็นดิกชันนารี ที่มีค่าคีย์เป็นตัวเลข
>>> for i, v in enumerate(['tic', 'tac', 'toe']): ... print i, v ... 0 tic 1 tac 2 toe
zip()
- ใช้จับคู่สองอนุกรม (ลิสต์หรือทูเปิลหรือผสมกัน) ที่มีจำนวนสมาชิกเท่ากัน แปลงรูปมาใช้งานแบบดิกชันนารี
>>> questions = ['name', 'quest', 'favorite color'] >>> answers = ['lancelot', 'the holy grail', 'blue'] >>> for q, a in zip(questions, answers): ... print 'What is your %s? It is %s.' % (q, a) ... What is your name? It is lancelot. What is your quest? It is the holy grail. What is your favorite color? It is blue.
reversed()
- ใช้กลับค่าสมาชิก
>>> for i in reversed(xrange(1,10,2)): ... print i ... 9 7 5 3 1
sorted()
- ใช้จัดเรียงสมาชิก
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] >>> for f in sorted(set(basket)): ... print f ... apple banana orange pear
- เงื่อนไขในประโยค
while
และif
ไม่จำเป็นต้องเป็นการเปรียบเทียบค่าเสมอไป แต่จะเป็นอะไรก็ได้ที่ ถ้าคืนค่าที่ไม่เป็นศุนย์หรือNone
จะถูกนับว่าเป็นจริง in
และnot in
ใช้ดูว่ามีค่าอยู่ในลำดับข้อมูลหรือเปล่า- สำหรับลิสต์
is
และis not
ใช้ดูว่าเป็นออปเจคต์เดียวกันหรือเปล่า - การเปรียบเทียบค่า มีลำดับความสำคัญน้อยกว่าการกระทำทางคณิตศาสตร์
- ถ้ามีการเปรียบเทียบหลายค่าในคำสั่งเดียว จะเรียงลำดับจากขวาไปซ้าย เช่น
a < b == c
>>> True == 1 True >>> 1 < 2 == 1 False >>> 1 < 2 == 2 True
- ตัวเปรียบเทียบทางตรรกะ มีความสำคัญน้อยที่สุด โดย
not
สำคัญที่สุด และor
สำคัญน้อยที่สุด คือ
A and not B or C
เขียนได้เป็น(A and (not B)) or C
- ตัวเปรียบเทียบทางตรรกะ จะเปรียบเทียบจากซ้ายไปขวา และถ้าจุดใดที่เมื่อเปรียบเทียบแล้วไม่เป็นจริง ประโยคส่วนที่เหลือจะไม่ถูกเปรียบเทียบต่อ ไพธอนเรียกการนี้ว่า ตัวกระทำลัดวงจร (short-circuit operators) และค่าที่คืนออกมาจากการเปรียบเทียบ จะเป็นค่าสุดท้ายที่ทำการเปรียบเทียบ
- สามารถกำหนดค่าผลของการเปรียบเทียบ ให้กับตัวแปรได้
>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance' >>> non_null = string1 or string2 or string3 >>> non_null 'Trondheim
- ออปเจคต์แบบลำดับ สามารถนำไปเปรียบเทียบกับออปเจคต์อื่นได้ โดยลิสต์น้ำหนักน้อยกว่าสตริง สตริงน้อยกว่าทูเปิล (อย่าจำมาก อาจเปลี่ยนแปลงได้ ให้ทดสอบตามรุ่นไพธอนที่ใช้จริง)
- การเปรียบเทียบยึดหลักจากซ้ายไปขวา และหยุดทันทีที่ผลออกมาไม่เป็นจริง
5.7 เงื่อนไข (More on Conditions)
5.8 น้ำหนักของข้อมูลแบบลำดับ (Comparing Sequences and Other Types)
(1, 2, 3) < (1, 2, 4) [1, 2, 3] < [1, 2, 4] 'ABC' < 'C' < 'Pascal' < 'Python' (1, 2, 3, 4) < (1, 2, 4) (1, 2) < (1, 2, -1) (1, 2, 3) == (1.0, 2.0, 3.0) (1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)
- Printer-friendly version
- Log in or register to post comments
- 5659 reads
Recent comments