最簡單的排序方法是使用排序(list) 函式,該函式會使用清單,並傳回含有這些元素的新清單。原始清單不會變更。
a = [5, 1, 4, 3] print(sorted(a)) ## [1, 3, 4, 5] print(a) ## [5, 1, 4, 3]
最常見的情況是將清單傳遞至已排序的() 函式,但實際上可以做為任何類型的疊代集合。舊版 list.sort() 方法以下提供詳細說明。排序() 函式似乎比 Sort() 容易很多,因此建議使用排序()。
透過選用引數,即可自訂已排序的() 函式。Rank() 選用引數反向=True,例如Order(list,verse=True) 一樣,使資料反向排序。
strs = ['aa', 'BB', 'zz', 'CC'] print(sorted(strs)) ## ['BB', 'CC', 'aa', 'zz'] (case sensitive) print(sorted(strs, reverse=True)) ## ['zz', 'aa', 'CC', 'BB']
使用 key= 自訂排序
如要進行更複雜的自訂排序,serial() 會使用選用的「key=」指定「鍵」這個函式可在比較之前轉換每個元素。索引鍵函式會採用 1 個值並傳回 1 個值,以及傳回的「proxy」值用於排序中的比較項目。
舉例來說,如果使用字串清單,指定 key=len (內建的 len() 函式) 就會按照長度從短到最長排序字串。排序會針對每個字串呼叫 len(),藉此取得 Proxy 長度值的清單,然後使用這些 Proxy 值排序。
strs = ['ccc', 'aaaa', 'd', 'bb'] print(sorted(strs, key=len)) ## ['d', 'bb', 'ccc', 'aaaa']
再以另一個範例指定「str.lower」作為鍵函數,是強制排序將大寫和小寫字母視為相同的方式:
## "key" argument specifying str.lower function to use for sorting print(sorted(strs, key=str.lower)) ## ['aa', 'BB', 'CC', 'zz']
您也可以傳入自己的 MyFn 做為主要函式,如下所示:
## Say we have a list of strings we want to sort by the last letter of the string. strs = ['xc', 'zb', 'yd' ,'wa'] ## Write a little function that takes a string, and returns its last letter. ## This will be the key function (takes in 1 value, returns 1 value). def MyFn(s): return s[-1] ## Now pass key=MyFn to sorted() to sort by the last letter: print(sorted(strs, key=MyFn)) ## ['wa', 'zb', 'xc', 'yd']
如果是更複雜的排序方式 (例如先按姓氏排序,再依照名字排序) 可以使用 itemgetter 或 attrgetter 函式,例如:
from operator import itemgetter # (first name, last name, score) tuples grade = [('Freddy', 'Frank', 3), ('Anil', 'Frank', 100), ('Anil', 'Wang', 24)] sorted(grade, key=itemgetter(1,0)) # [('Anil', 'Frank', 100), ('Freddy', 'Frank', 3), ('Anil', 'Wang', 24)] sorted(grade, key=itemgetter(0,-1)) #[('Anil', 'Wang', 24), ('Anil', 'Frank', 100), ('Freddy', 'Frank', 3)]
排序() 方法
清單上的排序() 方法是以遞增順序排序該清單,做為排序的替代方法,例如:list.sort()sort() 方法會變更基礎清單並傳回 None,因此請使用以下方式:
alist.sort() ## correct alist = blist.sort() ## Incorrect. sort() returns None
上面對排序() 來說,這是一個非常常見的誤解,它「不會傳回」已排序的清單。必須在清單上呼叫排序() 方法;這項函式不適用於任何可列舉的集合 (但上方的排序() 函式適用於所有項目)。排序() 方法會先加上已排序的() 函式,因此您可能會在較舊的程式碼中看到。排序() 方法不需建立新的清單,因此如果要排序的元素已在清單中,速度可能會更快。
元組
元組是指一組固定的大小元素分組,例如 (x, y) 座標。元組就像清單一樣,但不能變更且不會改變大小 (元組的其中一個元素可以變動,因此不會完全無法變更)。元組會演奏一種「結構體」角色,方便傳遞邏輯固定的大小組合。需要傳回多個值的函式可以只傳回值的元組。舉例來說,假設我想有一個 3D 座標清單,那麼自然的 Python 表示法就會是元組清單,而每個元組的大小都是 3,而每個元組的大小為 3,也就是一個 (x, y, z) 群組。
如要建立元組,只要列出括號中的值,並以半形逗號分隔即可。「空白」元組只是一對空白的括號。存取元組中的元素就像清單 -- len()、[ ]、for、in 等都是一樣的。
tuple = (1, 2, 'hi') print(len(tuple)) ## 3 print(tuple[2]) ## hi tuple[2] = 'bye' ## NO, tuples cannot be changed tuple = (1, 2, 'bye') ## this works
如要建立尺寸 1 的元組,請在第一個元素後加上半形逗號。
tuple = ('hi',) ## size-1 tuple
語法中的語法很有趣,但使用逗號來區分元組和一般大小寫 (以括號表示)。在某些情況下,您可以省略括號,而 Python 會從您想使用的元組的數字中移除。
如果將元組指派給相同大小的變數名稱元組,就會指派所有對應的值。如果元組的大小不相同,就會擲回錯誤。這項功能也適用於清單,
(x, y, z) = (42, 13, "hike") print(z) ## hike (err_string, err_code) = Foo() ## Foo() returns a length-2 tuple
名單理解程度 (選用)
清單理解是較先進的功能,在某些情況下就很適合,但在練習中並非必要,因此您不需要一開始就不需瞭解的內容 (例如跳過此部分)。清單理解是一種精簡的運算式,可撰寫會擴展為整個清單的運算式。假設我們有一份清單 num [1, 2, 3, 4],以下是計算其正方形清單的清單內容 [1, 4, 9, 16]:
nums = [1, 2, 3, 4] squares = [ n * n for n in nums ] ## [1, 4, 9, 16]
語法為 [ expr for var in list ]
-- for var in list
看起來像是一般的迴圈,但沒有冒號 (:)。系統會針對每個元素評估左側的 expr,為新清單提供值。以下為包含字串的範例,其中每個字串都會變更為大寫,並加上「!!!」已附加:
strs = ['hello', 'and', 'goodbye'] shouting = [ s.upper() + '!!!' for s in strs ] ## ['HELLO!!!', 'AND!!!', 'GOODBYE!!!']
您可以在 for 迴圈右側新增 if 測試來縮小結果範圍。系統會針對每個元素評估 if 測試,只包含測試為 true 的元素。
## Select values <= 2 nums = [2, 8, 1, 6] small = [ n for n in nums if n <= 2 ] ## [2, 1] ## Select fruits containing 'a', change to upper case fruits = ['apple', 'cherry', 'banana', 'lemon'] afruits = [ s.upper() for s in fruits if 'a' in s ] ## ['APPLE', 'BANANA']
練習:list1.py
如要練習本節的內容,請嘗試在 list1.py 中嘗試使用排序和元組 (位於基本練習) 中的問題。