排序是演算法課程的 ABC, 在 Python 的容器物件中, 不可變的字串與元組 (tuple) 內容無法排序 (因為排序會改變元素的順序); 無序的字典 (dict) 與集合 (set) 當然也無法排序, 只有串列 (list) 可以排序. 本篇是最近複習串列排序時的測試紀錄, 參考書籍 :
要對串列物件之內容排序有如下兩種方式 :
- 使用串列的 sort() 與 reverse() 方法 : 會直接改變原串列內元素的排序
- 使用內建函式 sorted() : 傳回排序後的新串列 (不影響原串列)
1. 使用串列的 sort() 與 reverse() 方法排序與倒序 :
呼叫 sort() 方法預設會將串列的元素值由小到大排列 (升冪), 如果是字串元素則依據其 Unicode 編碼排序, 如果要將元素值由大到小排列 (降冪), 則可傳入參數 reverse=True, 語法如下 :
list_obj.sort([key=None, reverse=False])
另外, 與串列元素順序有關的還有 reverse() 方法, 但它並不是將元素值由大到小降冪排序, 而是前軍做後軍, 後軍做前軍, 前後順序顛倒而已 (倒序), 嚴格來說不是排序, 語法如下 :
list_obj.reverse()
注意, reverse() 沒有任何參數. 順帶一提, reverse() 的倒序操作也可以用切片 [::-1] 來達成, 但[::-1] 與呼叫 reverse() 不同的是它不會改變原串列, 而是傳回倒序後的新串列, 例如 :
>>> lot=[2, 34, 16, 7, 18, 27]
>>> new_lot=lot[::-1]
>>> new_lot
[27, 18, 7, 16, 34, 2]
>>> lot
[2, 34, 16, 7, 18, 27]
>>> lot.reverse()
>>> lot
[27, 18, 7, 16, 34, 2]
sort() 方法有兩個備選參數, 其中 key 是在排序時要對每個元素呼叫的關鍵函式, 而 reverse 則是用來設定是要升冪或降冪排序 (預設是升冪), 例如 :
>>> lot=[2, 34, 16, 7, 18, 27]
>>> lot.sort() # 預設升冪排序
>>> lot
[2, 7, 16, 18, 27, 34]
>>> lot=[2, 34, 16, 7, 18, 27]
>>> lot.sort(reverse=True) # 指定降冪排序
>>> lot
[34, 27, 18, 16, 7, 2]
>>> lot=[2, 34, 16, 7, 18, 27]
>>> lot.reverse() # 倒序排列
>>> lot
[27, 18, 7, 16, 34, 2]
元素若是字串則按照每一個字元的 Unicode 編碼值大小逐一比對排序, 可用內建函式 ord() 查詢字元的 Unicode 編碼值, 例如 :
>>> string=['cC', 'aA', 'bB', 'Aa', 'Cc', 'Bb']
>>> string.sort()
>>> string
['Aa', 'Bb', 'Cc', 'aA', 'bB', 'cC']
>>> ord('A')
65
>>> ord('a')
97
>>> ord('B')
66
>>> ord('b')
98
可見 sort() 會依序從第一個字元開始一一比對 Unicode 編碼, 由於大寫字母的 Unicode 編碼比小寫的要小, 因此會排在前面. 任何語言的字串也是依據其 Unicode 編碼排序, 例如 :
>>> list_obj=['a', '我', '我們', '愛', 'abc', '你']
>>> list_obj.sort()
>>> list_obj
['a', 'abc', '你', '愛', '我', '我們']
>>> ord('我')
25105
>>> ord('愛')
24859
>>> ord('你')
20320
因為 '你' 的 Unicode 比 '愛' 的 Unicode 小, 所以 你' 排在 '愛' 的前面.
布林值串列也可以排序, 它是按照 Ture 與 False 相對應的整數值 1 與 0 去排序, 因此 False 會排在最前面, 例如 :
>>> list_obj=[True, True, False, True, False]
>>> list_obj.sort()
>>> list_obj
[False, False, True, True, True] # False 的值為 0, True 為 1, 故 False 排在前面
注意, 串列元素必須都是同類型資料才能呼叫 sort(), 否則會出現 TypeError 錯誤, 具體而言就是元素中有數值與字串混合情況的串列無法排序, 但布林值可以跟數值一起排序, 因為布林值其實就是 0 與 1 兩個整數. 而 reverse() 只是倒序操作而已, 並不涉及元素排序, 因此混合型態的串列呼叫 reverse() 是可以的, 例如 :
>> list_obj=['abc', 123]
>>> list_obj.sort() # 數值與字串混合的串列不可呼叫 sort()
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: '<' not supported between instances of 'int' and 'str'
>>> list_obj.reverse() # 混合型態串列可以呼叫 reverse()
>>> list_obj
[123, 'abc']
>>> list_obj=['abc', True] # 字串與布林值為混合型態, 不可排序
>>> list_obj.sort()
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: '<' not supported between instances of 'bool' and 'str'
>>> list_obj.reverse() # 混合型態串列可以呼叫 reverse()
>>> list_obj
[True, 'abc']
>>> list_obj=[3.14159, 123, True] # 布林值本質是整數, 與數值並非混合型態
>>> list_obj.sort()
>>> list_obj
[True, 3.14159, 123]
除了混合資料型態的串列無法呼叫 sort() 進行排序外, 複數串列也不行, 例如 :
>>> list_obj=[1+2j, 1+1j, 1-1j]
>>> list_obj.sort()
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: '<' not supported between instances of 'complex' and 'complex'
2. 使用內建函式 sorted() 排序 :
內建函式 sorted() 會將傳入串列預設以升冪排序後傳會心串列 (傳入 reverse=True 則可降冪排序), 不會改變原串列, 語法如下 :
sorted(list_obj [, key=None, reverse=False])
備選參數的用法與 sort() 方法的一樣, 例如 :
>>> lot=[2, 34, 16, 7, 18, 27]
>>> sorted(lot) # 傳回升冪排序後的新串列
[2, 7, 16, 18, 27, 34]
>>> sorted(lot, reverse=True) # 傳回降冪排序後的新串列
[34, 27, 18, 16, 7, 2]
>>> lot # 原串列不變
[2, 34, 16, 7, 18, 27]
字串串列同樣是以 Unicode 編碼排序, 例如 :
>>> string=['cC', 'aA', 'bB', 'Aa', 'Cc', 'Bb']
>>> sorted(string) # 傳回升冪排序後的新串列
['Aa', 'Bb', 'Cc', 'aA', 'bB', 'cC']
>>> sorted(string, reverse=True) # 傳回降冪排序後的新串列
['cC', 'bB', 'aA', 'Cc', 'Bb', 'Aa']
>>> string # 原串列不變
['cC', 'aA', 'bB', 'Aa', 'Cc', 'Bb']
與 sort() 方法一樣, 數值與字串混合的串列, 以及複數串列都無法用 sorted() 排序, 例如 :
>>> list_obj=['abc', 123] # 數值與字串混合 : 無法排序
>>> sorted(list_obj)
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: '<' not supported between instances of 'int' and 'str'
>>> list_obj=['abc', True]
>>> sorted(list_obj)
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: '<' not supported between instances of 'bool' and 'str'
>>> list_obj=[1+2j, 1+1j, 1-1j] # 複數串列無法排序
>>> sorted(list_obj)
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: '<' not supported between instances of 'complex' and 'complex'
參考 :
沒有留言:
張貼留言